手把手教你除錯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
#include<iostream> #include"functions.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(); return 0; }
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除錯單執行檔案
除錯結果如下:
[email protected]:~/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
std::cout << "Enter two numbers:" << std::endl;//斷點命中
(gdb) s
Enter two numbers:
int v1 = 0, v2 = 0;
(gdb) s //單步執行
std::cin >> v1 >> v2;
(gdb) n
6
<< " is " << v1 + v2 << std::endl;
(gdb) s
std::cout << "The sum of " << v1 << " and " << v2
(gdb) s
<< " is " << v1 + v2 << std::endl;
(gdb) s
The sum of 5 and 6 is 11
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);
[email protected]:~/testmake/Test_L1$ g++ -g -c -o testobj.o testobj.cc
[email protected]lidmango-pc:~/testmake/Test_L1$ ar rv libtest.a testobj.o
ar: creating libtest.a
a - testobj.o
[email protected]:~/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
[email protected]:~/testmake/Test_L1$ ./main
Enter two numbers:
6
The sum of 5 and 6 is 11
I am in a function!
I am in TestObj!
[email protected]:~/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>[email protected]:~/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 [email protected],
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
|