当您在C代码中访问超出范围的数组时,有时不会出现运行时错误。例如:
char array[1024];
char* ptr = array;
*(ptr-10) = 'a';
//or
*(ptr-4096) = 'a';
假设array
在堆栈上,我很好奇在任何情况下会让*(ptr-SIZE) = 'a'
抛出分段错误的最小SIZE是多少?
例如:
*(ptr-4096*1024) = 'a' // this will always throw a segmentation fault
*(ptr-4096*8) = 'a' // sometimes this will not throw a segmentation fault
2017/1/10,新增:
我很抱歉没有把问题说清楚(
我想知道的不仅仅是一个模糊的未定义。假设堆栈为高,而堆为低。因此,内存布局将是:
high *********
* stack * <- my array goes here
*********
* *
* * <- ptr may be here
* *
*********
* heap *
*********
* ??? * <- ptr may be here
*********
我当然知道
问题是C/C++实际上并没有对数组进行任何边界检查。这取决于操作系统,以确保您正在访问有效的内存
因此,上面的代码将导致操作系统内核调用do_page_fault
,并尝试查找地址的vma
,并检查vma->vm_start < address
是否为。
现在,让我们回到我问的问题:MIN SIZE,它将使*(ptr-SIZE) = 'a'
在任何情况下抛出分段错误。换句话说,我想知道do_page_fault
能负担得起的SIZE。这与C编译器无关,而是操作系统如何保护内存。
如果对array[i]
进行索引,其中i
小于0或大于1023,则符合C标准的编译器保留执行任何操作的权利。
这种情况下的行为被认为是未定义的。
试图猜测会发生什么是徒劳的。但是,如果您很好奇,可以随时检查生成的程序集。