std::map<int,int> bar;
int foo(int key)
{
bar.erase(key);
return 1;
}
int main()
{
bar[0] = foo(0);
return 0;
}
This code compiled with GCC 4.8 segs fault when checking memory usage with electric fence.
LD_PRELOAD=libefence.so.0.0 ./a.out
The problem comes from the fact that the compiler generates a code that starts to allocate a new entry in the map, then executes foo()
to get the value to put into bar[0]
. While running foo()
, the entry gets destroyed and the code finally ends by writing in non-allocated memory.
Does the way the operations are ordered depend on the compiler implementation, or is it specified by the C++ current standard?
The standard (§1.9 15) specifies that the evaluation of the two operands to a binary operator is unsequenced (unless in some specific cases):
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
This means that it does not mandate that one side of the assignment operation is evaluated before the other, and in fact, it is undefined behavior to depend on the order of these unsequenced operations.
This is also generally true for the order of evaluation of function arguments.
You need to break your assignment in two:
int result = foo(0);
bar[0] = result;