C阵列分段仅在某个阈值之后才出现故障

时间:2014-06-28 22:26:25

标签: c arrays segmentation-fault

我正在看这个简单的程序。我的理解是,尝试修改超出最大索引的内存地址的值应该导致分段错误。但是,以下代码运行没有任何问题。我甚至能够打印出所有6个数组索引0-> 6

main()
{
  int i;
  int a[3];

  for(i=0; i<6; i++)
        a[i] = i;

}

但是,当我将for循环更改为

for(i=0; i<7; i++)

并执行该程序,它将是段错误。 这几乎在我看来它是由malloc完成的某种额外填充。 为什么在第6个索引(s + 6)之后只发生?这种行为会在更长/更短的数组中发生吗?请原谅我的愚蠢程度如此低级的java程序员:)

4 个答案:

答案 0 :(得分:6)

  

在我看来,这似乎是由malloc完成的某种额外填充。

你没有调用malloc()。您在堆栈内存中将a声明为3个整数的数组,而malloc()使用堆内存。在这两种情况下,访问最后一个元素之后的任何元素(在这种情况下为第三个,a[2])是未定义的行为。当它完成堆内存时,通常会导致分段错误。

答案 1 :(得分:4)

好吧,malloc没有做到,因为你没有打电话给malloc。我的猜测是,额外的三次写入足以咀嚼你的帧指针和你的堆栈指针,但不是通过你的返回地址(但是第七次写入)。当您访问越界内存时,您的程序不会保证崩溃(尽管还有其他语言可以保证它),但不能保证崩溃。这是什么未定义的行为:不可预测。

答案 2 :(得分:2)

正如其他人所说,访问超出其限制的数组是不确定的行为。那会发生什么?如果访问不应访问的内存,则取决于内存的位置。

通常(但一般来说,细节可能因系统和编译器而异),可能会发生以下主要情况:

  • 您可以直接访问过程中直接位于&#34;后面的其他变量。数组。如果写入该内存,则只需修改其他变量的值即可。您可能不会得到段错误,因此您可能永远不会注意到为什么您的程序会产生错误的结果或行为如此奇怪或为什么在调试期间,您的变量具有您从未(知情)分配给它们的值。这是IMO,非常糟糕,因为你认为一切都很好,而不是。
  • 尤其是在堆栈上,您可以访问堆栈上的其他数据,如保存的处理器寄存器,甚至是函数结束时处理器应返回的地址。如果用其他一些数据覆盖这些数据,很难说清楚会发生什么。在这种情况下,段错误可能是所有可能的邪恶中的较小者。你根本不知道会发生什么。
  • 如果阵列之外的内存不属于您的进程,那么在大多数现代计算机上,您将收到段错误或类似异常(例如访问冲突或操作系统调用它)。

我可能已经忘记了可能发生的一些问题,但那些是IMO,如果你写的超出数组范围就会发生最常见的事情。

答案 3 :(得分:1)

这取决于可用的可用内存,如果可用的可用内存少,那么它将给出分段错误,否则它将使用额外的内存来存储数据,并且它不会给出分段错误。不需要malloc因为数组本身分配内存。

在您的系统中,内存仅适用于6个整数,当您尝试访问下一个内存(无法访问或说不可用)时,它会产生分段错误。