手把手教你调试Linux C++ 代码

来源:互联网 发布:ubuntu 安装skype 编辑:程序博客网 时间:2024/05/16 08:46

手把手教你调试Linux C++ 代码

软件调试本身就是一项相对复杂的活动,他不仅要求调试者有着清晰的思路,而且对调试者本身的技能也有很高的要求。Windows下Visual Studio为我们做了很多的工作,使初学者基本上可以获得一个所见即所得的调试体验,相对来说也比较容易上手。然而在linux平台下,一切都显得有些不同,倒不是说GDB有多难,只是对于习惯了visual studio的人来说刚开始会有些不适应。然而对于那些在windows 平台下使用windbg调试代码的人来说,情况会好很多,但是也要有个思维方式的转变以及调试命令的再适应过程。本文将带你开启GDB 调试 Linux 下 C/C++的大门。

Agenda

1. 准备条件

2. GDB调试单执行文件

3. GDB调试静态链接库

4. GDB调试动态链接库

 

1. 准备条件

由于Linux下没有visual studio, 对于程序的编译需要借助makefile,下面我先晒出一个简单的makefile,不求大而全,小巧可用就好。

复制代码
#makefileCC=gccCXX=g++RM=rm -fCPPFLAGS=-gLDFLAGS=-gLDLIBS=AR=arSRCS=main.cc functions.ccOBJS=$(subst .cc,.o,$(SRCS))all: mainmain: $(OBJS)    $(CXX) $(LDFLAGS) -o main $(OBJS) -L. $(LDLIBS)     main.o: main.cc functions.h testobj.hfunctions.o: functions.h functions.ccclean:    $(RM) $(OBJS)all-clean: clean    $(RM) main
复制代码

如下是相关的三个文件直接copy就可以使用

main.cc/functions.cc/functions.h

复制代码
 1 #include<iostream> 2 #include"functions.h" 5 int main() 6 { 7 std::cout << "Enter two numbers:" << std::endl; 8 int v1 = 0, v2 = 0; 9 std::cin >> v1 >> v2;10 std::cout << "The sum of " << v1 << " and " << v211 << " is " << v1 + v2 << std::endl;12 13 function();14 15 return 0;16 }
复制代码
1 #include<iostream>2 int function(void)3 {4     std::cout << "I am in a function!" << std::endl;5     return 0;6 }
1 int function(void);

将这4个文件放入一个目录下,到这个目录下直接执行make就会产生一个可执行文件main。

2. GDB调试单执行文件

复制代码
调试结果如下:solidmango@solidmango-pc:~/testmake/Test_L1$ gdb mainGNU gdb (Ubuntu 7.7-0ubuntu3) 7.7Copyright (C) 2014 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>Reading symbols from main...done.(gdb) b 2 //在第二行设置断点Breakpoint 1 at 0x400a4a: file main.cc, line 2.(gdb) r //全速运行Starting program: /home/solidmango/testmake/Test_L1/mainBreakpoint 1, main () at main.cc:77    std::cout << "Enter two numbers:" << std::endl;//断点命中(gdb) sEnter two numbers:8    int v1 = 0, v2 = 0;(gdb) s //单步执行9    std::cin >> v1 >> v2;(gdb) n5611    << " is " << v1 + v2 << std::endl;(gdb) s10    std::cout << "The sum of " << v1 << " and " << v2(gdb) s11    << " is " << v1 + v2 << std::endl;(gdb) sThe sum of 5 and 6 is 1114    function();(gdb)
复制代码

 

3. GDB调试静态链接库

对于静态链接库的调试和单个的执行文件相似,因为最终的文件都被链接在一起。对于静态链接库的调试需要两个额外两个辅助文件以及对makefile和main.cc稍作修改,具体改动如下:

复制代码
#makefileCC=gccCXX=g++RM=rm -fCPPFLAGS=-gLDFLAGS=-gLDLIBS=-ltest #changedAR=arSRCS=main.cc functions.ccOBJS=$(subst .cc,.o,$(SRCS))all: mainmain: $(OBJS) libtest.a #changed
$(CXX) $(LDFLAGS) -o main $(OBJS) -L. $(LDLIBS) main.o: main.cc functions.h testobj.h functions.o: functions.h functions.cc clean: $(RM) $(OBJS) all-clean: clean $(RM) main
复制代码

main.cc/testobj.cc/testobj.h

复制代码
#include<iostream>#include"functions.h"#include"testobj.h"int main(){std::cout << "Enter two numbers:" << std::endl;int v1 = 0, v2 = 0;std::cin >> v1 >> v2;std::cout << "The sum of " << v1 << " and " << v2<< " is " << v1 + v2 << std::endl;function();TestObj();return 0;}
复制代码

 

#include<iostream>int TestObj(void){    std::cout << "I am in TestObj!" << std::endl;    return 0;}
int TestObj(void);

执行结果如下:

复制代码
solidmango@solidmango-pc:~/testmake/Test_L1$ g++ -g -c -o testobj.o testobj.ccsolidmango@solidmango-pc:~/testmake/Test_L1$ ar rv libtest.a testobj.oar: creating libtest.aa - testobj.osolidmango@solidmango-pc:~/testmake/Test_L1$ makeg++  -g  -c -o main.o main.ccg++  -g  -c -o functions.o functions.ccg++ -g -o main main.o functions.o -L. -ltest solidmango@solidmango-pc:~/testmake/Test_L1$ ./mainEnter two numbers:56The sum of 5 and 6 is 11I am in a function!I am in TestObj!solidmango@solidmango-pc:~/testmake/Test_L1$ 
复制代码

 

4. GDB调试动态链接库对于动态链接库的调试和单个的执行文件差别较大,相对于静态链接库的调试只需要对makefile

稍作修改,具体改动如下:

生成相应的动态库并copy到系统目录

g++ -g -c -fPIC -o testobj.o testobj.ccg++ -g  -shared -o libtest.so testobj.osudo cp libtest.so /lib/libtest.so

makefile

复制代码
CC=gccCXX=g++RM=rm -fCPPFLAGS=-gLDFLAGS=-gLDLIBS=-ltestAR=arSRCS=main.cc functions.ccOBJS=$(subst .cc,.o,$(SRCS))all: mainmain: $(OBJS) libtest.so    $(CXX) $(LDFLAGS) -o main $(OBJS) -L. $(LDLIBS)     main.o: main.cc functions.h testobj.hfunctions.o: functions.h functions.ccclean:    $(RM) $(OBJS)all-clean: clean    $(RM) main
复制代码
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
调试结果如下:<br>solidmango@solidmango-pc:~/testmake/Test_L1$ gdb main
GNU gdb (Ubuntu 7.7-0ubuntu3) 7.7
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is freesoftware: you are freeto change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type"show copying"
and "show warranty"for details.
This GDB was configured as"x86_64-linux-gnu".
Type "show configuration"for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word"to search forcommands related to "word"...
Reading symbols from main...done.
(gdb) b TestObj
Breakpoint 1 at 0x400910
(gdb) r
Starting program: /home/solidmango/testmake/Test_L1/main
Enter two numbers:
7
8
The sum of 7 and 8 is 15
I am in a function!
 
Breakpoint 1, 0x0000000000400910 in TestObj()@plt ()
(gdb) s
Single stepping untilexit from function _Z7TestObjv@plt,
which has no line number information.
TestObj () at testobj.cc:3
3   {
(gdb) bt
#0  TestObj () at testobj.cc:3
#1  0x0000000000400b05 in main () at main.cc:17
(gdb) info sharedlibrary
From                To                  Syms Read   Shared Object Library
0x00007ffff7ddaae0  0x00007ffff7df54e0  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7bd8850  0x00007ffff7bd89c5  Yes         /lib/libtest.so
0x00007ffff792f5c0  0x00007ffff799299a  Yes (*)     /usr/lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ffff752d4a0  0x00007ffff7673413  Yes         /lib/x86_64-linux-gnu/libc.so.6
0x00007ffff720d610  0x00007ffff727c1b6  Yes         /lib/x86_64-linux-gnu/libm.so.6
0x00007ffff6ff4ab0  0x00007ffff7004995  Yes (*)     /lib/x86_64-linux-gnu/libgcc_s.so.1
(*): Shared library is missing debugging information.
(gdb) list
1   #include<iostream>
2   intTestObj(void)
3   {
4       std::cout <<"I am in TestObj!" << std::endl;
5       return0;
6   }
(gdb)

总结

本文总结了Linux下基于GDB的3种情况的调试方式,其中包括单个可执行文件,静态链接,动态链接,并给出了完整的makefile, 源文件,可操作性极强,建议感兴趣的朋友亲自动手操作演练,希望对大家有所帮助。