本文主要讨论用gdb追寻程序错误时,gdb所能定位问题的精度,以及影响gdb调试的因素。
1. 查看一个动态库(.so文件)或者可执行文件是否是debug版本。
readelf -S libxxx.so |grep debug
如果有输出,代表是debug版本
2. g++编译时是否加了-g对后期调试的影响
以下的测试代码,源代码为testso.cpp,并且链接了一个动态库libmyso.so,动态库libmyso.so是有so.cpp编译而来。其中so.cpp有一个越界的错误,运行后报segmentfault错误。
| testso.cpp testso.h
| so.cpp so.h
testso.cpp内容
#include <iostream>
#include <vector>
#include "./so.h"
using namespace std;
int main()
{
testso();
}
- 生成动态库,编译testso.cp 都不加 -g 参数
g++ so.cpp -fPIC -shared -o libmyso.so
g++ testso.cpp -l myso -o a.out
编译成功后,运行a.out。程序down掉生成core文件。
gdb ./a.out corefile
如图,能看到调用堆栈,但不能确定哪一行
- 生成动态库不加 -g,编译testso.cp 加 -g 参数
g++ so.cpp -fPIC -shared -o libmyso.so
g++ -g testso.cpp -l myso -o a.out
能定位到testso.cpp的第七行发生了错误
- 生成动态库加 -g 参数,编译testso.cp 不加 -g 参数
g++ so.cpp -fPIC -shared -o libmyso.so
g++ -g testso.cpp -l myso -o a.out
so.app可以定位到行,但是testso.cpp不能定位。
从上面可以简单总结:只有加了 -g 参数,gdb调试才能精确到行,不论是动态库还是自己的源代码。
3.gdb调试显示堆栈信息为 in ??()
gdb并不是万能,很多情况下可能会出现执行bt后堆栈信息全部是 in??。目前了解到的可能原因是:
- 程序异常退出时破坏了堆栈信息
- 运行环境与调试环境不一致
前一种情况,再想利用gdb进一步定位,会比较困难。可以考虑使用别的工具进行问题的定位,例如valgrind。个人在遇到此问题时,就是利用valgrind的内存分析最终找到了异常程序的崩溃问题所在。