我有两个关于数组的问题:
首先是关于以下代码:
int a[30]; //1
a[40]=1; //2
为什么第2行不给出segfault,它应该给出因为数组已被分配 只有30个int空间和在其分配空间之外的任何解除引用应该给出段错误。
第二:假设上面的代码有效,那么[40]有可能重写,因为它没有来自arrray的预留范围。
提前致谢。
答案 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。