segfault with array

时间:2011-01-13 10:05:34

标签: c++ c arrays segmentation-fault

我有两个关于数组的问题:

首先是关于以下代码:

int a[30];  //1
a[40]=1;   //2

为什么第2行不给出segfault,它应该给出因为数组已被分配 只有30个int空间和在其分配空间之外的任何解除引用应该给出段错误。

第二:假设上面的代码有效,那么[40]有可能重写,因为它没有来自arrray的预留范围。

提前致谢。

6 个答案:

答案 0 :(得分:4)

这是未定义的行为 - 它可能会崩溃,它可能会无声地破坏数据,它可能不会产生任何可观察到的结果。不要这样做。

在您的示例中,可能的解释是数组是堆栈分配的,因此数据周围有很多可以写入的地址,因此没有立即可观察到的结果。但是,取决于堆栈在系统上的增长方式(更大地址或更小地址的方向),这可能会覆盖调用堆栈中函数的返回地址和临时值,这会使程序崩溃或在程序尝试时使其行为异常从函数返回。

答案 1 :(得分:1)

出于性能原因,每次访问时C都不会检查数组大小。您还可以通过直接指针访问元素,在这种情况下无法验证访问权限。 只有在超出分配给流程的内存时才会发生SEGFAULT。

对于第二个问题,是的,它可以被覆盖,因为这个内存被分配给你的进程,并且可能被其他变量使用。

答案 2 :(得分:1)

这取决于系统分配该阵列的位置,如果由于临时位置40位于操作系统预留存储器中,那么您将收到段错误。

答案 3 :(得分:1)

只有当您为系统的其余部分执行非法操作时,您的应用程序才会崩溃:如果您尝试访问程序不拥有的虚拟内存地址,那么您的硬件会注意到这一点,会通知您操作系统,它将使用分段错误终止您的应用程序:您访问了一个您不应该访问的内存段。

但是,如果您访问随机内存地址(这就是您所做的:确保a[40]在数组a之外,但它可能在任何地方),你可以访问一个有效的存储单元(这就是发生在你身上的事情)。

这是一个错误:您可能会覆盖程序拥有的某些内存区域,因此有可能在其他地方破坏您的程序,但系统无法知道您是出于目的还是错误地访问它并且不会杀死您。< / p>

用托管语言编写的程序(即:在受保护环境中运行的程序检查任何内容)会注意到您的错误内存访问,但C不是托管语言:您可以随心所欲地做任何事情(只要您不要给系统的其他部分带来问题。)

答案 4 :(得分:1)

第2行的工作原理并没有抛出段错误是因为在C / C ++中,数组是指针。所以你的数组变量指向一些内存地址,例如1004.数组语法告诉你的程序从a的位置向下找多少字节来查找数组元素。

这意味着

printf("%p", a);
// prints out "1004"

printf("%p", a[0]);
// prints out "1004"

应该打印相同的值。

然而,

printf("%p", a[40]);
// prints out "1164"

从。

的地址返回sizeof(int)* 40的内存地址

答案 5 :(得分:0)

是的,它最终会被覆盖。

如果你malloc这个空间,你应该得到一个段错误(或者至少我相信如此),但是当使用一个没有分配空间的数组时,你将能够覆盖内存一段时间。它最终会崩溃,可能是在程序执行数组大小检查时,或者当你为其他东西保留了内存块时(不确定引擎盖下发生了什么)。

有趣的是,IIRC,efence也不会抓住这个:D。