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

时间:2011-08-31 17:38:16

标签: c++ c unix

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

int someints[100];
std::cerr << someints[100] << std::endl; //This is 1 past the end of the array.

第二行是否会导致段错?还是会打印出乱码?另外,如果我改变了那个内存,可能会导致特定行上的段错误,或者只有在其他人试图使用意外更改的内存时才会发生错误?

3 个答案:

答案 0 :(得分:9)

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

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

如果someints是堆栈上的数组并且是最后一个声明的变量,那么很可能会从堆栈顶部获得一些乱码或(非常不可能)调用可能让操作系统出现的页面错误使用SIGSEGV调整堆栈大小或终止您的流程。

想象一下,你在阵列后面声明了一个int

int someints[100];
int on_top_of_stack = 42;
std::cerr << someints[100] << std::endl;

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

答案 1 :(得分:4)

是的,如果程序无法访问该地址的内存,则可能会出现段错误。在你的情况下,它不太可能在堆栈上分配数组,并且只有100个字节长,堆栈大小要大得多(即Linux 2.4.X上每个线程8 MB),因此会有未初始化的数据。但在某些情况下它可能会崩溃。在任何一种情况下,此代码都是错误的,像Valgrind这样的分析器应该能够帮助您排除故障。

答案 2 :(得分:2)

第二行可能导致字面上任何发生,并且就语言规范而言仍然是正确的。它可以打印乱码,它可能因分段故障或其他原因而崩溃,它可能导致整个东海岸的电力消失,或者它可能导致规范demons to fly out of your nose ......

这是undefined behaviour的魔力。