读书人

【转】内存储器访问过界

发布时间: 2012-07-26 12:01:08 作者: rapoo

【转】内存访问过界
原文地址:http://hi.baidu.com/liheng_2009/blog/item/c065e880cc09129ef603a6e8.html

最近公司一台服务器的某个服务无故死掉,查看系统日志/var/log/messages ,发现有如下报错:

segfault at 0000000000000000 rip 0000000000878bd1 rsp 00007fffffa0e220 error 6


查找了一下,出现这个故障,一般是内存访问过界,以下是找到的资料。


/var/log/messages中一个关于APACHE的奇怪报错

最近以来,我的服务器/var/log/messages 中有一段日志,非常奇怪,而且我的apache经常并发很高,无故的死掉,我的环境是前端是nginx做代理,后端是apache,都在同一台机器上,下面我贴出日志,求大哥,大姐们,帮小弟看看了!
[root@168 logs]# tail /var/log/messages
Oct 9 00:29:20 168 kernel: httpd[24110]: segfault at 00007fff5989d878 rip 00002b8dd9595174 rsp 00007fff5989d880 error 6
Oct 9 00:34:55 168 kernel: httpd[24323]: segfault at 00007fff5989d878 rip 00002b8dd9595174 rsp 00007fff5989d880 error 6
Oct 9 00:47:26 168 kernel: httpd[24997]: segfault at 00007fff5989d878 rip 00002b8dd9595174 rsp 00007fff5989d880 error 6

答:

这种信息一般都是由内存访问越界造成的,不管是用户态程序还是内核态程序访问越界都会出core, 并在系统日志里面输出一条这样的信息。这条信息的前面分别是访问越界的程序名,进程ID号,访问越界的地址以及当时进程堆栈地址等信息,比较有用的信息是 最后的error number.
在上面的例子中,error number是6, 转成二进制就是110, 即bit2=1, bit1=1, bit0=0, 按照上面的解释,我们可以得出这条信息是由于用户态程序读操作访问越界造成的。
error number是由三个字位组成的,从高到底分别为bit2 bit1和bit0,所以它的取值范围是0~7.
bit2: 值为1表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界
bit1: 值为1表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界
bit0: 值为1表示没有足够的权限访问非法地址的内容,值为0表示访问的非法地址根本没有对应的页面,也就是无效地址
根据segfault信息调试定位程序bug:
#include<stdio.h>int main(){ int *p; *p=12; return 1;}
1. gcc testseg.c -o testseg -g,运行./testseg查看dmesg信息如下:
testseg[26063]: segfault at 0000000000000000 rip 0000000000400470 rsp 0000007fbffff8a0 error 6
2. 运行addr2line -e testseg 0000000000400470,输出如下:
/home/xxx/xxx/c/testseg.c:5 [...]

***********************

内存不足不会引起段错误。段错误通常出现在访问了非法的地址后,非法地址分为3类:
1. 访问的地址没有对应的物理内存。这类错误主要出现在越界访问,例如栈越界。比如说当前进程的栈只有5个页和它对应,共20k大小(x86平台),你访问的地址超过了这个范围,就会发生segmentation fault。

2.对地址的操作与该地址的属性不符合。例如该地址对应的内存是只读的,如文本段,你却试图进行写操作。

3.低权限访问高权限地址。这类情况发生在用户进程试图访问内核空间。例如x86中,TASK_SIZE以上的地址为内核空间,当用户态进程试图访问这些地址时,segmentation fault。********************


estseg[24850]: segfault at 0000000000000000 rip 0000000000400470 rsp 0000007fbffff8a0 error 6
这种信息一般都是由内存访问越界造成的,不管是用户态程序还是内核态程序访问越界都会出core, 并在系统日志里面输出一条这样的信息。这条信息的前面分别是访问越界的程序名,进程ID号,访问越界的地址以及当时进程堆栈地址等信息,比较有用的信息是最后的error number. 在上面的信息中,error number是4 ,下面详细介绍一下error number的信息:
在上面的例子中,error number是6, 转成二进制就是110, 即bit2=1, bit1=1, bit0=0, 按照上面的解释,我们可以得出这条信息是由于用户态程序读操作访问越界造成的。

error number是由三个字位组成的,从高到底分别为bit2 bit1和bit0,所以它的取值范围是0~7.
bit2: 值为1表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界
bit1: 值为1表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界
bit0: 值为1表示没有足够的权限访问非法地址的内容,值为0表示访问的非法地址根本没有对应的页面,也就是无效地址
根据segfault信息调试定位程序bug:
#include
int main()
{
int *p;
*p=12;
return 1;
}

1. gcc testseg.c -o testseg -g,运行./testseg查看dmesg信息如下:
testseg[26063]: segfault at 0000000000000000 rip 0000000000400470 rsp 0000007fbffff8a0 error 6
2. 运行addr2line -e testseg 0000000000400470,输出如下:
/home/xxx/xxx/c/testseg.c:5


参考资料:

http://en.wikipedia.org/wiki/Segmentation_fault

http://hi.baidu.com/sky_hacker/blog/item/86a933dcd6a858abcc116623.html

http://blog.5iwww.com/read.php/1109.htm


读书人网 >操作系统

热点推荐