4
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++ 当前标准指定?

4

1 回答 1

5

该标准(§1.9 15)指定对二元运算符的两个操作数的评估是无序的(除非在某些特定情况下):

除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的求值是无序的。

这意味着它不要求赋值操作的一侧在另一侧之前进行评估,事实上,依赖于这些未排序操作的顺序是未定义的行为。

这对于函数参数的评估顺序通常也是正确的。

你需要把你的任务分成两部分:

int result = foo(0);
bar[0] = result;
于 2015-10-14T17:39:57.740 回答