一、运行时错误
任何人写程序都会出错,正如《C++编程规范》所说,真正可怕的错误不是编译时的错误,而是运行时错误。
有的程序可以通过编译, 但在运行时会出现Segment fault(段错误)
这通常都是指针错误(一般就是空指针)引起的,或者访问了不能访问的内存(数组越界,系统保护)
二、core文件
我们不可能用GDB一句一句的去找,真正的英雄都善于使用手中的武器。这就是core file
所谓core,就是当程序down掉的时候,操作系统把程序的内存内容dump下来,这个动作就是core dump,动作的结果就是core文件
产生:
1.程序挂了,操作系统产生
2.通过gcore $pid命令直接导出相应进程的core文件,此命令运行后, 会恢复程序的执行, 不影响程序的运行
3.通过另一个进程发送SIGABRT信号给当前进程, 虽然也能产生core文件,但是程序随着一起终止掉
三、core文件开关设置
1.终端级别
怎么样才能让程序down掉的时候,自动core dump呢?可以通过 ulimit查看和设置
#查看core文件的信息 ulimit -a
[email protected]:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 20 file size (blocks, -f) unlimited pending signals (-i) 16382 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) unlimited virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [email protected]:~$
可以看到,core file size 是0,那就是说程序down了的时候,不会生成core文件,这个功能是关闭的。
可以使用 ulimit -c unlimited 设置允许当前生成没有大小限制的core file
[email protected]:~$ ulimit -c unlimited
只能对当前终端有效,退出就无效。
这样做,是因为只想临时生成core file,不需要每次crash时都自动生成。
2.用户级别
用户在自己的~/.bash_profile中加入
ulimit -S -c unlimited > /dev/null 2>&1
这样设置后允许当前用户生成没有大小限制的core dump文件
3.系统级别
(1)对所有用户
修改/etc/profile,加入或者修改
ulimit -S -c unlimited > /dev/null 2>&1
这样设置后允许所有用户生成没有大小限制的core dump文件。
优点:不需要重起系统
缺点:无法控制只让某些用户生成core dump文件
(2)上面这种方法也是有缺点的,那就是Tom用会产生core,Jerry也会产生,实行上我们只要Tom产生
修改/etc/security/limits.conf 可做到
ps.很多系统上限都可以通过修改这个文件改变,如最大子进程个数,最大打开文件数等等。这个文件开头有详细的注释,对如何修改这个文件做了说明。
[email protected]:/etc/security$ cat limits.conf # /etc/security/limits.conf #<domain> <type> <item> <value> #* soft core 0 #root hard core 100000 # End of file [email protected]:/etc/security$
我们看到了 * soft core 0 这一行,他表示对所有用户生产dump,但默认是注释了的
如果只想对某些用户或用户组打开core dump,可以加入
Tom soft core 0
@TomGroup soft core 0
#0是大小
优点:可以针对特定用户或特定组打开core dump文件
缺点:需要重起系统
四、core文件名称设置
1.pid信息
在/proc/sys/kernel/core_uses_pid中配置是否core带pid的扩展
文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxxx;(xxxxx如12345为pid)
为0则表示生成的core文件统一命名为core
[email protected]:~$ cat /proc/sys/kernel/core_uses_pid 0
可通过以下命令修改此文件(root)
[email protected]:/home/ju# echo "1" > /proc/sys/kernel/core_uses_pid
2.保存位置和文件名格式
/proc/sys/kernel/core_pattern 中配置生成文件的文件名和保存位置
[email protected]:~$ cat /proc/sys/kernel/core_pattern core #可通过以下命令修改此文件: [email protected]:/home/ju# echo "/tmp/core-%e-%p-%t" > /proc/sys/kernel/core_pattern #当然也可以是 sysctl -w kernel.core_pattern=/tmp/core-%e-%p-%t
可以将core文件统一生成到/tmp目录下,产生的文件名为 core-命令名-pid-时间戳
以下是参数列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名
#我是生成到自己的当前目录下方便使用
echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
五、调试core
用gdb进行查看core文件的内容
gdb [exec file] [core file]
之后基本上只用bt就可以找到信息了,当然还有where, frame, up, down, print等活用。
五、测试
实践出真知
1.代码
1: //a test file 2: 3: #include<iostream> 4: using namespace std; 5: 6: void test_fun() 7: { 8: char* szTmp = 0x00; 9: 10: //null ptr 11: *szTmp = 0x11; 12: } 13: 14: int main() 15: { 16: test_fun(); 17: return 0; 18: } 19:
2.编译
#编译时加 -g 参数得到符号
[email protected]:~/study/dump$ g++ -g -o dump dump.cpp [email protected]:~/study/dump$ ls -l 总用量 40 -rwxr-xr-x 1 ju ju 34437 2012-04-10 00:06 dump -rw-r--r-- 1 ju ju 154 2012-04-10 00:05 dump.cpp [email protected]:~/study/dump$
3.运行
运行出错,出现了core文件(会比较大)
[email protected]:~/study/dump$ ./dump 段错误 (core dumped) [email protected]:~/study/dump$ ls -l 总用量 160 -rw------- 1 ju ju 221184 2012-04-10 00:06 core-dump-17044-1333987618 -rwxr-xr-x 1 ju ju 34437 2012-04-10 00:06 dump -rw-r--r-- 1 ju ju 154 2012-04-10 00:05 dump.cpp [email protected]:~/study/dump$
4.调试
[email protected]:~/study/dump$ gdb ./dump core-dump-17044-1333987618 GNU gdb (GDB) 7.1-ubuntu Copyright (C) 2010 Free Software Foundation, Inc. #好多xxx #最后可以看到 Loaded symbols for /lib/ld-linux.so.2 Core was generated by `./dump‘. Program terminated with signal 11, Segmentation fault. #0 0x080485a4 in test_fun () at dump.cpp:9 9 *szTmp = 0x11; (gdb) #很容易就定位了,一般指针出错都会有完整的堆栈信息,而数组越界则堆栈信息不完整显示
六、声明
1.不对文章正确性做保证,只为本人学习之用。
2.本文参考了好多其它作者的文章,也引用了一些文字,对他们的知识共享精神表示感谢。
3.本文链接:
(1)好像加了这个就会被网易屏蔽
(2)http://pppboy.blog.163.com/blog/static/30203796201231011715932/
4.本文可以任意转载修改使用,但请保证文章完整性,不要误导他人。
5.注意身体,早点休息,不做就别做,做就做好。