一、GDB和coredump
GDB是Linux下非常好用且强大的调试工具。GDB可以调试C、C++、Go、java、 objective-c、PHP等语言。对于一名Linux下工作的程序员,GDB是必不可少的工具。
Coredump叫做核心转储,它是进程运行时在突然崩溃的那一刻的一个内存快照。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个文件里。该文件也是二进制文件,可以使用gdb、elfdump、objdump或者windows下的windebug、solaris下的mdb进行打开分析里面的具体内容。
这里使用Linux的gdb调试coredump文件。
二、如何配置生成coredump文件
首先在编译我们的程序时需要加 -g 选项使程序生成调试信息: gcc -g core_test.c -o core_test
(一)、设置core文件大小
虽然我们知道进程在coredump的时候会产生core文件,但是有时候却发现进程虽然core了,但是我们却找不到core文件。这是因为在Linux下要程序dump时生成core文件是需要设置的:
- 可以使用 ulimit -c 查看core开关,如果为0表示关闭,不会生成core文件;
- 可以使用 ulimit -c [filesize] 设置core文件大小,当最小设置为4之后才会生成core文件;
- 可以使用 ulimit -c unlimited 设置core文件大小为不限制,这时再用 ulimit –c core文件大小已经为unlimited,这是常用的做法;
- 注意上面的设置是计算机每次重启后都重置的,需要重新设置。如果需要每次开机就执行,则需要将这句命令写到 /etc/profile 环境变量文件。可以使用命令 :
echo "ulimit -c unlimited" >> /etc/profile
然后再敲命令 source /etc/profile 让/etc/profile文件修改后立即生效。
(二)、设置core文件命名和保存路径
我们可以通过在 /proc/sys/kernel/core_pattern 文件中设置 core 文件名和保存路径,命令如下:
echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern // 指定在/corefile文件夹下生成coredump文件
命名的参数列表:
- %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 添加命令名。
三、调试core文件
按照上面的步骤设置好了之后,当我们的程序发生coredump崩溃时,就会在我们上面设置的路径下按照设置的文件命名格式生成core文件,使用gdb调试core文件,先进到刚才设置的core文件路径下,使用命令开始调试:
gdb [exec file] [core file] // [exec file]为你需要调试的程序的路径,[core file]为coredump问件名
进入gdb中后可以使用命令 bt 查看堆栈信息,gdb可以直接指出是在代码的哪一行发生了崩溃。
如果你的程序引用了一些第三方的库,程序是崩溃在第三方库中,也可以用gdb查看是库中哪里发生了崩溃。使用命令 info sharedlibrary 查看gdb加载了哪些库,使用命令 set solib-search-path + 库文件的路径 加载你使用的第三方库
加载完第三方库之后,再使用 bt 命令就可以查看到第三方库中崩溃在哪一个文件的哪一行。
使用命令 info threads 可以查看所有线程正在运行的指令信息
使用命令 thread apply all bt 打开所有线程的堆栈信息。
查看指定线程堆栈信息:threadapply threadID bt ,如:thread apply 5 bt 查看线程ID为5的线程信息。