据我所知,每当程序试图访问未经授权的内存时,就会引发segfault。
以下代码将一个int内存块分配给p
,然后尝试在某个未知地址进行写入。
#include <stdlib.h>
int main(void)
{
int* p = malloc(sizeof(int));
p[1000] = 12;
return 0;
}
为什么这个代码在试图访问这个有点随机的地址时没有引发分段错误?
相关
未定义的行为有多不定义?-解释未定义的行为,但不解释p[1000] = 12
指令不引发segfault的原因。
下面的代码为p分配一个一int内存块,然后尝试在某个未知地址进行写入。
这不是一个"未知"地址;地址是在具有CCD_ 4的系统上的CCD_。
当前大多数操作系统都使用需求分页。在这样的系统上,对malloc
的第一次调用可能会分配一个新的页内存。常见的页面大小为4096
,在该(可写)页面中的任何位置写入都不会产生分段错误。
另一方面,这个程序很可能会产生分段故障:
int main(void)
{
int* p = malloc(sizeof(int));
int j;
for (j = 1000; j < 100000; j++) p[j] = 12;
return 0;
}
通过执行p[1000] = 12;
,您只需在地址(p+1000)
处放置一个值。没有什么会导致segfault。该地址可能是一个有效的地址,尽管p
无法合法获取。
启动程序时,操作系统会将程序内存划分为可读(代码部分)和可写(数据部分和堆)。现在,它将取决于存储在d引用的指针中的地址。
如果它指向有效的可写内存,则不会引发分段故障异常,否则将引发分段故障例外。
这完全取决于您在什么平台和操作系统上运行此代码。如果您编译此代码并在没有MMU或MPU的处理器上运行,则不会出现任何异常/分段错误。
据我所知,每当程序试图访问未经授权的内存。
当您试图访问非分页内存块时引发Segfault,没有任何授权。
那么p[1000]是否指向非分页区域?它是未定义的,但在您的情况下,每个动态内存分配都需要分配在一个内存页中,在x86系统中,该内存页通常为4096字节,当您调用malloc时,它会在分配的页面中搜索可用空间,如果没有找到合适的内存块(在以前分配的页面或释放的页面中),则会放置一个新的页面请求,并分配一个内存页面。现在malloc为您保留已分配页面的一部分(如果请求的大小+标题小于页面大小),并返回其指针。
现在,当你试图访问p[1000]时,你实际上是在访问非保留(非mallocated)区域,但该区域是分页的(之前分配的剩余部分),所以不会引发segfault,但如果你试图访问像p[10000]这样的更大索引,你可能会得到segfault。
这里有更多的例子