原文链接:Linux下使用gdb调试C/C++程序
发布时间:2015-08-27 14:55:29
在笔者工作实践中,使用gdb调试C++程序和调试C程序,他们稍有不同,下面是使用总结。
一、编译选项
1 2 3 4 5
| -g 生成调试信息
-gstabs+ 以stabs格式生成调试信息,并且包含仅供gdb使用的额外调试信息生成调试信息,是阻止编译器将局部变量优化的寄存器里,
笔者在调试C++程序时,不加这个选项,所有的变量都打印不出来,gdb提示说没有这个符号
|
二、打断点
对于C程序,代码都是函数封装,打断点很容易,但是C++代码都是类封装,而且函数还可以重载前2种打断点的方式主要用于C程序,后3种多用于C++程序
1 2 3 4 5 6 7 8 9
| 1、b funcName 即在函数入口处打断点
2、b lineNum 在某一行打断点
3、b className::funcName或者 b className::funcName(type,type) 在某个类的某个函数入口打断点,由于类的函数有重载,可以在函数名内加上参数类型
4、b fileName:lineNum 在某个源文件的某一行打断点
5、b fileName:funcName 在某个源文件的某个函数入口打断点
|
三、常用命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 1、finish 一直执行到当前函数返回,即跳出当前函数
2、r 运行程序(run)
3、n 执行下一条语句(next 不会进入函数内部)
4、s 执行下一条语句(step 会进入函数内部)
5、回车键 重复执行上一条命令
6、c 继续执行直到下一个断点(continue)
7、p 打印变量的值(print)
8、bt 查看函数堆栈(backtrce)
9、q 退出gdb调试(quit)
10、info break 查看断点信息
11、delete breakNum 删除某个断点
|
四、bt命令调试段错误
在Linux下编程,一不下心就会出现段错误(Segmentation fault),关于段错误的产生,笔者目前只是大概知道是内存的非法访问造成的,比如访问空指针,指针越界访问都会造成段错误,关于本质原因,还需要研究Linux内存管理、进程空间等知识,这方面有待后续深入研究。下面演示如何利用 core文件定位程序段错误。
测试代码:segfault.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#include<stdio.h>
void test_seg_fault() { printf("test_seg_fault() start.\n"); char *p=NULL; *p = 'a'; printf("test_seg_fault() end.\n"); }
void main() { test_seg_fault(); }
|
1、编译程序生成可执行文件
1
| gcc -g segfault.c -o segfault
|
2、生成Core文件
执行程序:./segfault
1 2 3
| [root@localhost MyDir]# ls
core.8450 segfault segfault.c
|
3、启动gdb,打印栈信息
1
| gdb ./segfault ./core.8450
|
然后执行:bt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./segfault'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004004e2 in test_seg_fault () at segfault.c:13
13 *p = 'a';
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.x86_64
(gdb) bt
#0 0x00000000004004e2 in test_seg_fault () at segfault.c:13
#1 0x00000000004004ff in main () at segfault.c:19
(gdb)
|
4、分析结果
本实例中,程序崩溃后,保留了2层栈的信息,#0 栈,是程序发生崩溃时所在的栈,即是在test_seg_fault函数内发生崩溃,在segfault.c文件的第13行,这一句发生段错误,到此定位完成。其实函数每调用一层,就会有一层栈的信息,最上面的总是 #0 号栈,即程序当前所在的栈,这很符合压栈操作。
由于笔者的水平有限,出错在所难免,恳请读者拍砖指正,谢谢阅读。