当前位置: 技术问答>linux和unix
【咨询】Linux操作系统下读未申请的内存或导致异常吗?谢谢!
来源: 互联网 发布时间:2016-08-05
本文导语: 如题 | 取决于这个“未申请的内存”在什么地方。 有些禁止访问的内存,读取也会产生异常。 比如这行代码,会出现Segmentation fault : int i = *(int *)100; 如果是允许访问的内存,那就不...
如题
|
取决于这个“未申请的内存”在什么地方。
有些禁止访问的内存,读取也会产生异常。
比如这行代码,会出现Segmentation fault : int i = *(int *)100;
如果是允许访问的内存,那就不会有exception,但是结果未必是程序员预期的。
比如栈区;比如堆区无人申请的内存或者其他模块申请的内存。
int *p = (int *)malloc(sizeof(int));
*p = 123;
printf("%dn", *p);
free(p); // free之后p已经算是“未申请的内存”
printf("%dn", *p); // 这样肯定不会有异常,但读出来的值是多少就不一定了。
有些禁止访问的内存,读取也会产生异常。
比如这行代码,会出现Segmentation fault : int i = *(int *)100;
如果是允许访问的内存,那就不会有exception,但是结果未必是程序员预期的。
比如栈区;比如堆区无人申请的内存或者其他模块申请的内存。
int *p = (int *)malloc(sizeof(int));
*p = 123;
printf("%dn", *p);
free(p); // free之后p已经算是“未申请的内存”
printf("%dn", *p); // 这样肯定不会有异常,但读出来的值是多少就不一定了。
|
这就要看内核的内存管理了。
在linux中内存以页的形式分配给程序,操作系统会设立了页表(有可能是层次结构的),每一个虚拟页在表中都有对应的一个项,其中包括 该页的权限信息(读,写或执行)
|
对于内核,发生Segmentation fault 是因为访问了非法内存。而这个非法内存可以理解为:访问的虚地址不存在,相应的页面表项是空的,也可以理解为虽然地址已经映射到物理内存,但是访问属性不允许,如对一个只读页面进行了写操作。这些都是在页面异常处理函数里面进行处理的,最后如果该页面确实是非法访问,函数通常是输出Segmentation fault,并发出信号终止进程。
其次就是在ELF可执行文件中分成了几个段,装载程序会把这几个段根据各自的段描述项把文件映射到内存指定的位置,通常说来代码段和只读数据是一段,加载到0X8040000的地方,并且页面属性为执行。后面是数据段,页面为读写不可执行,高地址初始化为进程的栈,页面属性为读写执行,数据段和栈之间的虚地址空间为堆,可供进程自由申请回收。
这样看来,如果读低地址空间(int i = *(int *)100;小于0X8048000),就会因为页表没有映射而段错误。如果写代码段的地址(long *p = (long*)0x8048ff0; *p = 0;), 就会因为页面属性不允许写而出现段错误。
而对于使用malloc分配的堆区内存,在分配的时候就建立好了页面映射,并且至少是可读写的,所以一般不会出问题,一般malloc之间管理一个内存池,即使free了以后,也不是撤销映射,暂时还不归还给内核。因此再printf("%dn", *p);也不会出问题。
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。