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

42 篇文章 0 订阅

手把手教你调试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,不求大而全,小巧可用就好。

复制代码
#makefile
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g
LDFLAGS=-g
LDLIBS=
AR=ar

SRCS=main.cc functions.cc
OBJS=$(subst .cc,.o,$(SRCS))

all: main
main: $(OBJS)
    $(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
复制代码

如下是相关的三个文件直接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 " << v2
11 << " 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 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>
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/main

Breakpoint 1, main () at main.cc:7
7    std::cout << "Enter two numbers:" << std::endl;//断点命中
(gdb) s
Enter two numbers:
8    int v1 = 0, v2 = 0;
(gdb) s //单步执行
9    std::cin >> v1 >> v2;
(gdb) n
5
6
11    << " is " << v1 + v2 << std::endl;
(gdb) s
10    std::cout << "The sum of " << v1 << " and " << v2
(gdb) s
11    << " is " << v1 + v2 << std::endl;
(gdb) s
The sum of 5 and 6 is 11
14    function();
(gdb)
复制代码

 

3. GDB调试静态链接库

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

复制代码
#makefile
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g
LDFLAGS=-g
LDLIBS=-ltest #changed
AR=ar

SRCS=main.cc functions.cc
OBJS=$(subst .cc,.o,$(SRCS))

all: main
main: $(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.cc
solidmango@solidmango-pc:~/testmake/Test_L1$ ar rv libtest.a testobj.o
ar: creating libtest.a
a - testobj.o
solidmango@solidmango-pc:~/testmake/Test_L1$ make
g++  -g  -c -o main.o main.cc
g++  -g  -c -o functions.o functions.cc
g++ -g -o main main.o functions.o -L. -ltest 
solidmango@solidmango-pc:~/testmake/Test_L1$ ./main
Enter two numbers:
5
6
The sum of 5 and 6 is 11
I 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.cc
g++ -g  -shared -o libtest.so testobj.o
sudo cp libtest.so /lib/libtest.so

makefile

复制代码
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g
LDFLAGS=-g
LDLIBS=-ltest
AR=ar

SRCS=main.cc functions.cc
OBJS=$(subst .cc,.o,$(SRCS))

all: main
main: $(OBJS) libtest.so
    $(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
复制代码
?
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 free software: you are free to 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 for commands 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 until exit 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   int TestObj( void )
3   {
4       std::cout << "I am in TestObj!" << std::endl;
5       return 0;
6   }
(gdb)

总结

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值