Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dangerous implicit conversion in emplace

Tags:

c++

c++11

The following code compiles without any errors/warnings with gcc 6.3 (https://godbolt.org/g/sVZ8OH), but it contains a dangerous undefined behavior due to invalid memory access marked below. The root cause is the implicit conversion performed in emplace_back. Can anyone suggest a good way or best practices to avoid such bugs in code?

#include <iostream>
#include <vector>

struct Foo
{
  explicit Foo(const int& i) : i{i} {}

  void foo() const { std::cout << i; }  // invalid memory access, as i is an invalid ref!!
  const int& i;
};

void bar(const double& d) {
  std::vector<Foo> fv;
  fv.emplace_back(d);
}
like image 425
user2736667 Avatar asked Dec 30 '16 21:12

user2736667


2 Answers

If you are going to accept a const reference, but you don't want a reference to a temporary, declare an additional constructor with an rvalue reference argument - and delete it.

struct Foo
{
  explicit Foo(const int& i) : i{i} {}
  explicit Foo(const int&& i) = delete;  // This preferentially matches a reference to a
                                         // temporary, and compilation fails.

  void foo() const { std::cout << i; }  // invalid memory access, as i is an invalid ref!!
  const int& i;
};

(I am assuming that the actual problem is more complex than just an int. For an int, holding it by value is the right answer.)

like image 131
Martin Bonner supports Monica Avatar answered Sep 27 '22 19:09

Martin Bonner supports Monica


Can anyone suggest a good way or best practices to avoid such bugs in code?

When your class stores a const reference to another object, you, as a programmer, are taking on the responsibility of making sure that you don't end up storing a dangling reference.

Unless you have a strong reason for storing a const reference, I would recommend storing a value.

struct Foo
{
  explicit Foo(const int& i) : i{i} {}

  void foo() const { std::cout << i; }
  int i;
};
like image 26
R Sahu Avatar answered Sep 27 '22 19:09

R Sahu