Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are std::begin and std::end "not memory safe"?

In this blog post, Eric Niebler states that:

What is wrong with std::begin and std::end? Surprise! they are not memory safe. Consider what this code does:

extern std::vector<int> get_data();
auto it = std::begin(get_data());
int i = *it; // BOOM

std::begin has two overloads for const and non-const lvalues. Trouble is, rvalues bind to const lvalue references, leading to the dangling iterator it above.

I'm having trouble understanding his point and why it is a dangling reference. Could someone explain?

like image 515
Davidbrcz Avatar asked Sep 25 '22 15:09

Davidbrcz


2 Answers

The get_data function returns an object. When used the way shown, that object will be a temporary object, which will be destructed once the full expression ends. The iterator now references a vector object which no longer exists, and can't be dereferenced or used in any useful way.

like image 60
Some programmer dude Avatar answered Oct 19 '22 14:10

Some programmer dude


I think Eric's point about std::begin is that it silently accepts an rvalue container as an argument to begin with. On the face of it, the problem with the code is also exemplified in

auto it = get_data().begin();

But std::begin is a free function template, it can be made to reject rvalues without needing to add the proper reference qualifiers to each container's begin members. By "just" forwarding it misses an opportunity to add a layer of memory safety to code.

Ideally, the overload set could have benefited from the addition of

template< class C > 
void begin( C&& ) = delete;

That one would have caused the code in the blog post to be flat out rejected on the spot.

like image 53
StoryTeller - Unslander Monica Avatar answered Oct 19 '22 14:10

StoryTeller - Unslander Monica