std::map<int,int> bar;
int foo(int key)
{
bar.erase(key);
return 1;
}
int main()
{
bar[0] = foo(0);
return 0;
}
使用电围栏检查内存使用情况时,使用GCC 4.8编译的代码会出现故障。
LD_PRELOAD=libefence.so.0.0 ./a.out
问题来自于编译器生成的代码开始在地图中分配新条目,然后执行foo()
以获取要放入bar[0]
的值。在运行foo()
时,条目被破坏,代码最终通过写入未分配的内存来结束。
操作的排序方式取决于编译器实现,还是由C ++当前标准指定?
答案 0 :(得分:5)
标准(§1.915)指定对二元运算符的两个操作数的求值是无序的(除非在某些特定情况下):
除非另有说明,否则评估各个运营商的操作数 并且个别表达的子表达式没有被排除。
这意味着它并没有强制要求分配操作的一方在另一方之前进行评估,事实上,它是未定义的行为,取决于这些未经测序的操作的顺序。
对于函数参数的评估顺序,这通常也是正确的。
你需要将你的作业分成两部分:
int result = foo(0);
bar[0] = result;