手把手教你調試Linux C++ 代碼(一步到位包含靜態庫和動態庫調試)


手把手教你調試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
調試結果如下:
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, 源文件,可操作性極強,建議感興趣的朋友親自動手操作演練,希望對大家有所幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM