行为差异(GCC和Visual C++)

Pra*_*rav 12 c++ valgrind segmentation-fault

请考虑以下代码.

#include <stdio.h>
#include <vector>
#include <iostream>

struct XYZ { int X,Y,Z; };
std::vector<XYZ> A;

int rec(int idx)
{

   int i = A.size();
   A.push_back(XYZ());
   if (idx >= 5)
     return i;

   A[i].X = rec(idx+1);

   return i;
}

int main(){
  A.clear();
  rec(0);
  puts("FINISH!");

}
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚代码在Linux(使用的IDE:Code :: Blocks)上给出分段错误的原因,而在Windows(使用的IDE:Visual C++)上却没有.

当我使用Valgrind来检查实际问题是什么时,我得到了这个输出.

我到Invalid write of size 4了四个不同的地方.那么为什么我使用Visual C++时代码没有崩溃?

我错过了什么吗?

ere*_*eOn 17

递归调用rec()可能会在您为其赋值时修改向量.

如果你更换会发生什么

A[i].X = rec(idx+1);
Run Code Online (Sandbox Code Playgroud)

int tmp = rec(idx+1);
A[i].X = tmp;
Run Code Online (Sandbox Code Playgroud)

此外,只是总结有用的注释:操作的操作数评估顺序=是未指定的,并且由于向量未预先分配,因此在递归调用期间可能会发生多次调整rec(),从而使向量中的值的任何迭代器无效.

  • 为了更精确一点,在递归调用中,对`push_back`的调用可能导致前一个指针无效. (4认同)
  • 难道它基本上不是`i = ++ i;`问题(除了右侧A的修改隐藏在递归调用中)?编译器可以在`rec`之前或之后评估`A [i]`以及它是否"有效",取决于它选择这样做的顺序. (2认同)
  • @ereOn:是的!我认为你的答案是正确的.与"="运算符关联的操作数的评估顺序是_unspecified_. (2认同)