大家都知道在 Linux 可以用 gdb 来调试应用程序,当然前提是用 gcc 编译程序时要加上 -g 参数。
我这篇文章里将讨论一下用 gdb 来调试动态链接库的问题。
首先,假设我们准备这样的一个动态链接库:
引用:
库名称是: ggg
动态链接库文件名是: libggg.so
头文件是: get.h
提供这样两个函数调用接口:
int get ()
int set (int a)
要生成这样一个动态链举胡锋接库,我们首先编写这样一个头文件:
/************关于本文档********************************************
*filename: get.h
*********************************************************************/
int get ()
int set (int a)
然后准备这样一个生成动态链接库的源文件:
/************关于本文档********************************************
*filename: get.cpp
*********************************************************************/
#include
#include "get.h"
static int x=0
int get ()
{
printf ("get x=%d\n", x)
return x
}
int set (int a)
{
printf ("set a=%d\n", a)
x = a
return x
}
然后我们用 GNU 的 C/C++ 编译器来生成动态链接库做逗,编译命令如下:
引用:
g++ get.cpp -shared -g -DDEBUG -o libggg.so
这样我们就准备好了动态链接库了,下面我们编写一个应用程序来调用此动态链接库,源代码如下:
/************关于本文档********************************************
*filename: pk.cpp
*********************************************************************/
#include
#include "get.h"
int main (int argc, char** argv)
{
int a = 100
int b = get ()
int c = set (a)
int d = get ()
printf ("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d)
return 0
}
编译此程序用下列命令,如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录,比如 /lib 或 /usr/lib 之类的,就用下面这条命令:
引用:
g++ pk.cpp -o app -Wall -g -lggg
否则就用下面这条命令:
引用:
g++ pk.cpp -o app -Wall -g -lggg -L`pwd`
下面我们就开始调试上面命令生成的 app 程序吧。如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录,比如 /lib 或 /usr/lib 之类的,调试就顺利完成,如下:
引用:
#gdb ./app
GNU gdb 6.4-debian
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) b main/* 这是在程序的 main 处设置断点 */
Breakpoint 1 at 0x804853c: file pk.cpp, line 7.
(gdb) b set /* 这是在程序的 set 处设置断点 */
Function "set" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y /* 这里必须选择 y 调试程序才会跟踪到动态链接库内部去 */
Breakpoint 2 (set) pending.
(gdb) run /* 开始运行我们的程序,直到遇见断点时暂停 */
Starting program: /data/example/c/app
Breakpoint 3 at 0xb7f665f8: file get.cpp, line 11.
Pending breakpoint "set" resolved
Breakpoint 1, main (argc=1, argv=0xbfArrayArray0504) at pk.cpp:7
7 int a = 100
(gdb) n /* 继续执行程序的下一行代码 */
8 int b = get ()
(gdb) n /* 程序执行到了我们断点所在的动态链接库了 */
get x=0
Array int c = set (a)
(gdb) n
Breakpoint 3, set (a=100) at get.cpp:11
11 printf ("set a=%d\n", a)
(gdb) list /* 查看当前代码行周围的代码,证明我们已经跟踪到动态链接库的源代码里面了 */
6 printf ("get x=%d\n", x)
7 return x
8 }
Array int set (int a)
10 {
11 printf ("set a=%d\n", a)
12 x = a
13 return x
14 }
(gdb) n
set a=100
12 x = a
(gdb) n
13 return x
(gdb) n
14 }
(gdb) n
main (argc=1, argv=0xbfArrayArray0504) at pk.cpp:10
10 int d = get ()
(gdb) n
get x=100
11 printf ("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d)
(gdb) n
a=100,b=0,c=100,d=100
12 return 0
(gdb) c
Continuing.
Program exited normally.
(gdb) quit /* 程序顺利执行结束 */
如果我们没有把动态链接库放到指定目录,比如/lib里面,调试就会失败,过程如下:
引用:
# gdb ./app
GNU gdb 6.4-debian
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) b main
Breakpoint 1 at 0x804853c: file pk.cpp, line 7.
(gdb) b set
Function "set" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (set) pending.
(gdb) run /* 虽然调试 *** 作都一样,但程序执行失败 */
Starting program: /data/example/c/app
/data/example/c/app: error while loading shared libraries: libggg.so: cannot open shared object file: No such file or directory
Program exited with code 0177.
(gdb) quit
GDB是一个强大的命令行调试工具。虽然X Window提供了GDB的图形版DDD,但是我仍然更钟爱在命令行模式下使用GDB。大家知道命令行的强喊誉大就是在于,其可以形成执行序列,形成脚本。UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已有工具的命令,就可以做出一个非常强大的功能。于是UNIX下的软件比Windows下的软件更能有机地结合,各自发挥各自的长处,组合成更为强劲的功能。而Windows下的图形软件基本上是各自为营,互相不能调用,很不利于各种软件的相互集成。在这里并不是要和Windows做个什么比较,所谓“寸有所长,尺有所短”,图形化工具还是有不如命令行的地方。
1 GDB概述
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。
一般来说,GDB主要帮忙你完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。
从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发乱裤现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。
一个调试示例
源程序:tst.c
代码:
1 #include
2
3 int func(int n)
4 {
5 int sum=0,i
6 for(i=0i
7 {
8 sum+=i
9 }
10return sum
11 }
12
13
14 main()
15 {
16 int i
17 long result = 0
18 for(i=1i<=100i++)
19 {
20result += i
21 }
22
23 printf("result[1-100] = %d"郑陪段, result )
24 printf("result[1-250] = %d", func(250) )
25 }
编译生成执行文件:(Linux下)
root@linux:/home/benben/test# gcc -g tst.c -o tst
使用GDB调试:
代码:
root@linux:/home/benben/test# gdb tst <---------- 启动GDB
GNU gdb 5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-suse-linux"...
(gdb) l <-------------------- l命令相当于list,从第一行开始例出原码。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)