优麒麟技术论坛

 找回密码

linux core 调试实例 [复制链接]


文中提到:
大多数UNIX调试程序都使用core文件以检查进程终止时的状态。
如书上表10-1所示,当进程接收到例如SIGABRT(异常终止)、SIGBUS(硬件故障)、SIGSEGV(无效内存引用)等信号的时候会产生相应的core文件,该core文件复制了进程的存储镜像。在运行程序的时候,我们会经常遇到Segmentation fault,也就是段错误,表示该进程进行了一次无效的内存访问。对于此类情况,我们很难发现问题具体是出现在程序的哪一行,如果是一小段程序,我们可以直接用gdb一步一步跟踪调试,但是如果程序规模很大,这样做显然就不实现了。回过头来,我们发现对于此类错误,程序会接收到SIGSEGV(无效内存引用)信号,而该信号在终止程序的同时,会在当前目录产生一个相应的core文件。因此,我们可以让gdb根据该core文件分析中断的位置,也就是出现该错误的位置。首先,我们应该现查看当前系统是否开启了core文件支持(以GNU/Linux为例):
  • ~ $ ulimit -c
  • 0
  • ~ $ ulimit -c unlimited
  • ~ $ ulimit -c
  • unlimited
  • 默认情况下,core dump生成的文件名为core,而且就在程序当前目录下。新的core会覆盖已存在的core。通过修改/proc/sys/kernel/core_uses_pid文件,可以将进程的pid作为作为扩展名,生成的core文件格式为core.xxx,其中xxx即为pid 方法:sudo echo "1" > /proc/sys/kernel/core_uses_pid 通过修改/proc/sys/kernel/core_pattern可以控制core文件保存位置和文件格式。例如:将所有的core文件生成到/corefile目录下,文件名的格式为core-命令名-pid-时间戳. 方法:sudo echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

0表示未开启,大于0的表示默认core文件的大小,如果超过此大小,则截断,这会造成core文件的信息不完整,因此我们这里将其设置为unlimited,也就是无限大。接下来,我们写一段C代码来测试:
  • #include <stdio.h>
  • char *str;
  • void core_test()
  • {
  •     printf("%c\n",*str);
  • }
  • int main(int argc, char *argv[])
  • {
  •     core_test();
  •     return 0;
  • }

然后,依次进行编译(无警告无错误),运行(段错误),并结合产生的core文件调试:
  • ~ $ gcc -o test test.c -g
  • ~ $ ./test
  • Segmentation fault (core dumped)
  • ~ $ file core
  • core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './test'
  • ~ $ gdb test core
  • GNU gdb (Gentoo 7.3.1 p1) 7.3.1
  • Copyright (C) 2011 Free Software Foundation, Inc.
  • ...
  • Core was generated by `./test'.
  • Program terminated with signal 11, Segmentation fault.
  • #0  0x08048574 in core_test () at test.c:7
  • 7                printf("%c\n",*str);
  • (gdb) where
  • #0  0x08048574 in core_test () at test.c:7
  • #1  0x0804859d in main (argc=1, argv=0xbfed0214) at test.c:12
  • (gdb) quit

很明显,问题是出在这里:
  • #0  0x08048574 in core_test () at test.c:7
  • 7                printf("%c\n",*str);

字符指针str未经初始化就试图(解除引用)访问它所指向的内存空间,导致出现无效的内存访问。其中where命令用来查看当前调用栈信息。

发表于 2013-4-1 16:03:00
回复

使用道具 举报

小黑屋|优麒麟    

GMT+8, 2022-1-20 15:12 , Processed in 0.018058 second(s), 17 queries .

Copyright ©2013-2022 Ubuntu Kylin. All Rights Reserved .

ICP No. 15002470-2 Tianjin

快速回复 返回顶部 返回列表