C/C++程序可以通过读取数组末尾(UNIX)来解决错误吗?

Joh*_*0te 8 c c++ unix

我知道你可以读过数组的结尾 - 我现在想知道你是否可以通过执行读操作来解决错误.

int someints[100];
std::cerr << someints[100] << std::endl; //This is 1 past the end of the array.
Run Code Online (Sandbox Code Playgroud)

第二行真的可能导致段错误还是仅仅打印乱码?另外,如果我更改了那个内存,是否会导致该特定行上出现seg-fault ,或者只有当其他东西试图使用该意外更改的内存时才会发生故障?

Bla*_*iev 10

这是未定义的行为,完全取决于操作系统为进程安排的虚拟内存布局.通常你可以:

  • 访问属于您的虚拟地址空间但有无意义值的一些乱码,或者
  • 尝试访问受限制的内存地址,在这种情况下,内存映射硬件会调用页面错误,操作系统会决定是否打击您的进程或分配更多内存.

如果someints是堆栈上的数组并且是声明的最后一个变量,则很可能会从堆栈顶部获得一些乱码或(非常不可能)调用页面错误,该错误可能让操作系统调整堆栈大小或者使用a SIGSEGV.

想象一下,你int在数组之后声明了一个:

int someints[100];
int on_top_of_stack = 42;
std::cerr << someints[100] << std::endl;
Run Code Online (Sandbox Code Playgroud)

然后很可能该程序应该打印42,除非编译器以某种方式重新排列堆栈上的声明顺序.

  • 我刚刚在我的系统上得到42,但没有特别的理由期望`on_top_of_stack`将在'someints`之后立即分配.例如,如果较小的偏移量更便宜,则可能有充分的理由将较小的对象放在堆栈帧的开头. (3认同)
  • 如果您打开优化器,则所有投注均已关闭.声明的顺序与内存中的顺序无关,除了结构中的字段. (2认同)