GDB调试技巧

调试信息的生成

进行gdb调试时最重要的是要保存调试信息,.c与.cpp文件编译之后可生成.o、.a、.so以及可执行文件等等。如果依赖文件中存在.c或.cpp文件,编译时加上-g选项,那么就可以用gdb调试目标文件了。值得注意的是:如果将.c或.cpp编译(加上了-g)成.o文件,再将这些.o文件编译(没有用到-g)成.so,虽然编译成.so时没有用到-g,但.so文件中仍然保存了调试信息,仍可用gdb调试。

保存调试信息的根源在于用-g编译.c与.cpp文件,其他中间过程可不用-g。

利用部分源文件调试

gdb调试时,如果有源代码,那就能单步执行,一步一步的查看结果,能方便的定位问题。但是,如果源代码很庞大,而公司又不允许把全部代码拿出去调试,那就可以只拿一部分代码出去调试。在此我做了一个小实验来说明这个问题。

假设代码放在3个目录下:

1. show目录,包含2个文件:

【1】show.h

void show();

【2】show.c

#include "show.h"

#include <stdio.h>

 

void show()

{

    printf("show/n");

}

2. display目录,包含2个文件:

【1】display.h

void display()

【2】display.c

#include "display.h"

#include <stdio.h>

 

void display()

{

    printf("display/n");

}

3.main目录,包含一个文件:

#include "../show/show.h"

#include "../display/display.h"

 

int main()

{

    show();

       display();

}

 

将show.c编译成共享库:gcc -shared -g -o libshow.so show.c,将libshow.so拷贝到/lib下。

将display.c编译为.o文件:gcc -g -c display.c。

生成可执行文件:gcc -g -o main main.c ../display/display.o –lshow。

此时可用gdb main进行单步调试,执行到show();时按s进入函数。如果将.so与main拷贝到另一台机器上,不拷贝源码,运行gdb main时由于没有源码,无法单步调试,此时将main.c拷贝过来即可单步调试。

如果想进入show函数调试,可将show.c拷贝过来,放到跟main同样的路径下。

同理,如果想进入display函数调试,可将display.c拷贝过来,放到跟main同样的路径下。

无论编译时源文件的路径怎样,部署之后,只需将源文件与可执行文件放在同一目录即可进行调试。

另外一个问题是,如果没有拷贝main.c,又想调试display函数怎么办?这就需要用到断点:

【1】gdb main

【2】l display.c:1

【3】b display.c:6

【4】r

可以看到已经执行到display函数里边了,这下又可以通过按n来进行单步调试了。同样的方法适用于调试show函数,不过用“l show.c:1”时会提示找不到源文件(这一步可不必执行),此时不用理会直接用“b show.c:6”设置断点即可。

段错误的处理

程序运行时经常遇到烦人的段错误,可用core文件进行调试。

敲入指令“ulimit -c”,如果输出0就表示不会产生core文件,应该进行修改以允许core文件的产生,“ulimit -c unlimited”或者“ulimit -c 1024”等等。

假设运行main时产生了段错误并产生了core文件“core.2182”,此时就可以用“gdb main core.2182”进行调试,就可以看到出错信息,如果有源文件并且编译时用到了-g,那就还可以看到出错的是哪条语句。

 

总的来说,编译.c或.cpp时加上-g选项保存调试信息,可将我们关注的部分源代码与可执行文件放在同一目录下进行单步调试跟踪,当程序出现段错误时可利用core文件查看出错信息。

 

参考:http://blog.csdn.net/xxffnn2002/article/details/4880773

posted @ 2013-08-15 13:45  ☆y急速の灵感 ★  阅读(340)  评论(0编辑  收藏  举报