我有一个关于阵列两个问题:
第一个是关于下面的代码:
int a[30]; //1
a[40]=1; //2
为什么不是2号线给予段错误,也应该给,因为阵列已分配的只有30 INT空间及其分配的空间之外的任何非关联化应该给段错误。
第二:假设上面的代码工作中有任何机会,一个[40]将获得超过写的,因为它不被arrray的保留范围。
提前致谢。
我有一个关于阵列两个问题:
第一个是关于下面的代码:
int a[30]; //1
a[40]=1; //2
为什么不是2号线给予段错误,也应该给,因为阵列已分配的只有30 INT空间及其分配的空间之外的任何非关联化应该给段错误。
第二:假设上面的代码工作中有任何机会,一个[40]将获得超过写的,因为它不被arrray的保留范围。
提前致谢。
这是不确定的行为 - 它可能会崩溃,也可能默默损坏的数据,它可能会产生没有明显的效果,任何东西。 不这样做。
在您的例子中,可能的解释是,该数组栈上分配等有广泛写入访问阵列周围的地址,所以是没有直接观察到的结果。 但是这取决于如何(哪个方向 - 以更大的地址,或更小的地址)堆栈增长您的系统上,这可能覆盖的功能调用堆栈的返回地址和临时,这将你的程序崩溃或使其出现异常时,它会尝试从函数返回。
出于性能方面的原因,C不会在每次访问它时检查数组的大小。 您也可以访问通过直接指针元素在这种情况下,有没有办法来验证访问。 如果你是从分配给您的进程内存的内存设计缺陷才会发生。
对于第二个问题,是的,它可以为这个内存分配给你的进程,并可能通过其他变量用来被改写。
这取决于哪里有系统分配的数组,如果因果位置40处于有效系统保留的内存,那么你将得到段错误。
如果你试图访问你的程序不拥有了某个虚拟内存地址,发生的事情是,你的硬件会发现,会通知你的操作系统,如果你做一些你的系统的其余部分非法您的应用程序只会崩溃它会杀死分段故障您的应用程序:你访问你不应该存储段。
不过,如果你访问一个随机的内存地址(这是你做了什么:肯定a[40]
是你的阵列外的a
,但也可能是别的地方),你可以访问一个有效的存储单元(这是发生什么事了) 。
这是一个错误:你可能会改写你的程序拥有一些内存区域,从而危及到其他地方打破你的程序,但系统无法知道,如果你的目的或错误地访问它并不会杀你。
写在托管语言程序(即:计划在受保护的环境检查任何运行),会发现你的错误的内存访问,但C不是一个托管语言:你可以自由地做任何你想要的(只要你不产生问题的系统的其它部分)。
其原因线2级的作品和不抛出段错误是因为,在C / C ++,阵列是指针。 所以你的数组变量指向一些内存地址如1004数组要告诉你的计划中有许多个字节的位置下移如何寻找一个数组元素。
这意味着
printf("%p", a);
// prints out "1004"
和
printf("%p", a[0]);
// prints out "1004"
应打印相同的值。
然而,
printf("%p", a[40]);
// prints out "1164"
返回的存储器地址是的sizeof(int)的* 40从的地址向下。
是的,它最终会被覆盖。
如果你malloc
的空间,你应该得到一个段错误(或至少我这样认为),但使用未分配空间的数组时,你就可以覆盖内存一会儿。 它最终会崩溃,有可能当程序执行数组大小检查或者也许当你打别的东西(不知道这是怎么回事引擎盖下)保留的内存块。
有趣的是,IIRC,efence表示不会赶上这两种:d。