1. 程式人生 > >《gdb除錯之基礎篇》

《gdb除錯之基礎篇》

        這篇文章通過一個簡單的例項描述了gdb的基本用法,並對gdb支援的語言極其基本選項進行了介紹。對於有一定經驗的建議看下一篇文章:《gdb除錯之實用技巧篇》

1. gdb介紹

        gdbGNU釋出的一款功能強大的程式除錯工具,它可以讓我們深入洞悉一個程式是怎麼執行的,也可以幫我們記錄一個程式在崩潰的時候所執行的操作。具體一點它可以幫我們完成下面四件事情

  • 啟動我們的程式,並指定任何可以影響程式執行的條件。
  • 設定斷點,讓我們的程式停止在某處,然後檢視堆疊是否正常。
  • 追蹤程式出錯時執行的程式碼。
  • 在程式執行中,調整引數,以測試潛在的bug

       就具體除錯方法而言,根據使用場景不同,gdb

除錯可分為三種類型

  • 除錯一個可執行檔案
  • 除錯一個coredump檔案
  • 除錯一個正在執行的程序

2. 一個簡單的例項

       實際應用的時候,遇到的情況可能是千差萬別的,也遠比下面所要舉的例子更加複雜和困難。這裡先針對gdb三種除錯型別的前兩種舉一個簡單的例項,以期帶你走進gdb的除錯世界。下面的測試程式碼,先從終端輸入兩個字串,然後再將其輸出到終端。

編譯執行

      編譯上面的程式碼並執行,結果發現程式的輸出結果不對,輸入給b的內容本來是”01234”,但是輸出的時候卻變成了”ghijk”,而且發生了core dump(這裡省略了glibc輸出的memory map資訊)。如下所示:

除錯可執行檔案

       可執行檔案的除錯參考附錄A,從中我們知道字串a的賦值後,b也被改變了。因為給a賦值的時候超過了給a開闢的空間長度。

除錯coredump檔案

       除錯core檔案的命令格式為:gdbPROGRAM CORE。根據gdb除錯core檔案的資訊,可以知道發生core dump時程式正在執行的操作為test.c中的第18行程式碼,即free操作。

       綜合上述資訊,可知道b的輸出錯誤是因為a賦值越界引起的,而產生coredump的原因是free出錯。至於為什麼free出錯,其實也是因為a的賦值越界,導致glibc開闢給btrunk的頭部資訊被覆蓋導致的。關於記憶體的錯誤可以參考附錄B

中的文件。

3. gdb支援的語言

       gdb能支援很多語言,可以在啟動gdb之後執行”set language”來檢視當前版本gdb所支援的語言。一般預設為C語言,可以用”show language”命令來檢視,需要修改的話還是用”set language ***”,但請務必加上要設定的目標語言。


4. gdb的啟動選項

       除了最簡潔的啟動辦法(直接執行”gdb”就可以啟動gdb,退出的話”ctrl+d”或者”quit”),gdb還支援很多命令列選項和引數,用於在啟動gdb時就設定需要除錯的內容以及除錯方式。這些選項可以在gdbhelp檔案中查詢到,下表列出其中最為常用的一些選項:


5. gdb的內部命令

        gdb的內部命令,可用來設定gdb的除錯環境並除錯可執行檔案。和shell一樣,gdb環境下也支援tab命令補全特性。下表列出了常見的內部命令:


       除了上述內部命令的使用之外, gdb環境下也可直接執行shell命令,一般格式為”shell COMMAND”。這有一個例外,那就是make命令。


附錄A------gdb除錯可執行檔案例項

[[email protected] share]# gdb test        >>>>>>>>>>>>>>>啟動gdb時直接指定可執行檔案

GNU gdb (GDB) Red Hat Enterprise Linux  (7.0.1-32.el5)

Copyright (C) 2009 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-redhat-linux-gnu".

For bug reporting instructions, please  see:

<http://www.gnu.org/software/gdb/bugs/>...

Reading symbols from  /data/yinsy/share/test...done.

(gdb) l               >>>>>>>>>>>>>>>顯示(預設10行)原始碼

1        #include<stdio.h>

2        #include<stdlib.h>

3        #include <string.h>

4

5        int main()

6        {

7           char* a=malloc(3);

8           char* b=malloc(5);

9

10          printf("please enter a string  for b:");

(gdb)                >>>>>>>>>>>>>>>直接按enter,重複上一條子命令

11          scanf("%s",b);

12          printf("please enter a string  for a:");

13           scanf("%s",a);

14          printf("address:  a=%p,b=%p\n",a,b);

15          printf("strlen :  a=%d,b=%d\n",strlen(a),strlen(b));

16          printf("content:  a=%s,b=%s\n",a,b);

17

18          free(a);

19          free(b);

20       }

(gdb) b 9            >>>>>>>>>>>>>>>在第9行設定斷點

Breakpoint 1 at 0x40058c: file test.c,  line 9.

(gdb) b 17            >>>>>>>>>>>>>>>在第17行設定斷點

Breakpoint 2 at 0x400657: file test.c,  line 17.

(gdb) i b              >>>>>>>>>>>>>>>顯示已經設定的斷點資訊

Num      Type           Disp Enb  Address            What

1        breakpoint     keep y   0x000000000040058c in main at test.c:9

2        breakpoint     keep y   0x0000000000400657 in main at test.c:17

(gdb) r               >>>>>>>>>>>>>>>開始執行可執行檔案

Starting program: /data/yinsy/share/test

Breakpoint 1, main () at test.c:10         >>>>>>>>>>>>>>>在第一個斷點出停下來,等待命令

10          printf("please enter a string  for b:");

(gdb) p a             >>>>>>>>>>>>>>>列印指標a的值,以及其指向地址的內容,當前為空

$1 = 0x601010 ""

(gdb) p b            >>>>>>>>>>>>>>>列印指標b的值,以及其指向地址的內容,當前為空

$2 = 0x601030 ""

(gdb) s              >>>>>>>>>>>>>>>單步執行

11          scanf("%s",b);

(gdb)               >>>>>>>>>>>>>>>繼續單步執行,給b賦值“01234”

please enter a string for b:01234

12          printf("please enter a string  for a:");

(gdb)

13          scanf("%s",a);

(gdb) p b           >>>>>>>>>>>>>>>給a賦值前,列印b指標及其指向地址的內容,仍為“01234”

$3 = 0x601030 "01234"

(gdb) s

please enter a string for  a:abcdefghijklmnopqrstuvwxyzabcdefghijk

14          printf("address:  a=%p,b=%p\n",a,b);

(gdb) p a

$4 = 0x601010 "abcdefghijklmnopqrstuvwxyzabcdefghijk"

(gdb) p b           >>>>>>>>>>>>>>>給a賦值後,b指標指向地址的內容也發生變化,變為“ghijk”

$5 = 0x601030 "ghijk"

(gdb) c             >>>>>>>>>>>>>>>繼續執行程式,直到遇到第二個斷點暫停

Continuing.

address: a=0x601010,b=0x601030

strlen : a=37,b=5

content: a=abcdefghijklmnopqrstuvwxyzabcdefghijk,b=ghijk

Breakpoint 2, main () at test.c:18

18          free(a);

(gdb) s             >>>>>>>>>>>>>>>繼續單步執行free(a)操作,程式出現錯誤,glibc提示invalid next size

*** glibc detected ***  /data/yinsy/share/test: free(): invalid next size (fast): 0x0000000000601010  ***

======= Backtrace: =========

/lib64/libc.so.6[0x3e13c7245f]

/lib64/libc.so.6(cfree+0x4b)[0x3e13c728bb]

/data/yinsy/share/test[0x400660]

/lib64/libc.so.6(__libc_start_main+0xf4)[0x3e13c1d994]

/data/yinsy/share/test[0x4004b9]

======= Memory map: ========

00400000-00401000 r-xp 00000000 08:06  674109                              /data/yinsy/share/test

00600000-00601000 rw-p 00000000 08:06  674109                              /data/yinsy/share/test

00601000-00622000 rw-p 00601000 00:00  0                                   [heap]

3893600000-389360d000 r-xp 00000000 08:05 278756                          /lib64/libgcc_s-4.1.2-20080825.so.1

389360d000-389380d000 ---p 0000d000 08:05 278756                          /lib64/libgcc_s-4.1.2-20080825.so.1

389380d000-389380e000 rw-p 0000d000 08:05 278756                          /lib64/libgcc_s-4.1.2-20080825.so.1

3e13800000-3e1381c000 r-xp 00000000 08:05  278556                          /lib64/ld-2.5.so

3e13a1b000-3e13a1c000 r--p 0001b000 08:05  278556                         /lib64/ld-2.5.so

3e13a1c000-3e13a1d000 rw-p 0001c000 08:05  278556                          /lib64/ld-2.5.so

3e13c00000-3e13d4e000 r-xp 00000000 08:05  283255                          /lib64/libc-2.5.so

3e13d4e000-3e13f4e000 ---p 0014e000 08:05  283255                          /lib64/libc-2.5.so

3e13f4e000-3e13f52000 r--p 0014e000 08:05  283255                          /lib64/libc-2.5.so

3e13f52000-3e13f53000 rw-p 00152000 08:05  283255                          /lib64/libc-2.5.so

3e13f53000-3e13f58000 rw-p 3e13f53000  00:00 0

2aaaaaaab000-2aaaaaaaf000 r-xp  2aaaaaaab000 00:00 0                       [vdso]

2aaaaaaaf000-2aaaaaab3000 rw-p  2aaaaaaaf000 00:00 0

2aaaaaade000-2aaaaaadf000 rw-p  2aaaaaade000 00:00 0

7ffffffea000-7ffffffff000 rw-p 7ffffffe9000  00:00 0                      [stack]

ffffffffff600000-ffffffffffe00000 ---p  00000000 00:00 0                   [vsyscall]

Program received signal SIGABRT, Aborted.

0x0000003e13c30265 in raise () from  /lib64/libc.so.6

(gdb) s

Single stepping until exit from function  raise,

which has no line number information.

Program terminated with signal SIGABRT,  Aborted.

The program no longer exists.

(gdb) q             >>>>>>>>>>>>>>>退出gdb除錯

附錄B------深入理解glibc的記憶體管理

相關資料無法插入本文件,以下連結供參考。

1)http://gee.cs.oswego.edu/dl/html/malloc.html

2)https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=1120d4df8487b78a9f1ceb5394968d6ab651986e;hb=439bda3209b768c349b98b8ceecf0fa8d94600e9

3) http://blog.csdn.net/phenics/article/details/777053

4)http://stackoverflow.com/questions/10943907/linux-allocator-does-not-release-small-chunks-of-memory

5) http://www.cnblogs.com/sunyubo/archive/2010/05/05/2282170.html

6) http://www.ibm.com/developerworks/cn/linux/l-memory/

7)http://www.cnblogs.com/sunyubo/archive/2010/05/05/2282170.html

相關推薦

gdb除錯基礎

        這篇文章通過一個簡單的例項描述了gdb的基本用法,並對gdb支援的語言極其基本選項進行了介紹。對於有一定經驗的建議看下一篇文章:《gdb除錯之實用技巧篇》 1. gdb介紹         gdb是GNU釋出的一款功能強大的程式除錯工具,它可以讓我們深入洞悉

Qt入門基礎 ( 二 ) :Qt項目建立、編譯、運行和發布過程解析

qt 5 對話 讓我 進度 qmake ctr deploy 設定 設置 轉載請註明出處:CN_Simo。 題解:   本篇內容主講Qt應用從創建到發布的整個過程,旨在幫助讀者能夠快速走進Qt的世界。   本來計劃是講解Qt源碼靜態編譯,如此的話讀者可能並不能清楚地知

Qt入門基礎 ( 一 ) :Qt4及Qt5的下載與安裝

mingw ins 第3版 點擊 調試 但我 關系 構建 eas 轉載請註明出處:CN_Simo. 導語: Qt是一個跨平臺的C++圖形界面應用程序框架。它提供給開發者建立圖形用戶界面所需的功能,廣泛用於開發GUI程序,也可用於開發非GUI程序。Qt很容易擴展,並

[轉]Eclipse插件開發基礎(1) 插件開發的基礎知識

作用 原本 services 註冊 1-1 啟動 創建 abs class 原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/08/13/eclipse_plugin_1_0_2.html 名詞翻譯   有一些名詞在翻譯的

[轉]Eclipse插件開發基礎(3) 插件的測試與調試

case ews ... 有時 sam cancel workbench osgi ring 原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/08/17/eclipse_plugin_1_1_2.html 1. 使用JU

[轉]Eclipse插件開發基礎(4) OSGi框架

動作 update 執行 創建 class cti 指定 mpc 代碼 原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/08/18/eclipse_plugin_1_2_1.html   1. 什麽是OSGi框架   O

視頻教程:Java七大外企經典面試套路基礎

視頻教程:Java七大外企經典面試套路之基礎篇 視頻教程:Java七大外企經典面試套路之基礎篇 Java是Sun公司推出的一種編程語言。它是一種通過解釋方式來執行的語言,語法規則和C++類似。同時,Java也是一種跨平臺的程序設計語言。 本教程主要給

chrome瀏覽器開發常用快捷鍵基礎-遁地龍卷風

rom 後臺 加載網頁 打開鏈接 上一個 tps 保存 參考 瀏覽器開發 1.標簽頁和窗口快捷鍵   打開新的標簽頁,並跳轉到該標簽頁 Ctrl + t   重新打開最後關閉的標簽頁,並跳轉到該標簽頁 Ctrl + Shift + t   跳轉到下一個打開的標簽頁 Ctrl

T4模板:T4模板基礎

教程 添加 介紹 9.png 輸出 com 明顯 gin ecif 一、回顧 上一篇文章 ——T4模板之菜菜鳥篇,我們囫圇吞棗的創建了與“T4模板”有關的文件。在創建各個文件的這一個過程中,我們對於T4模板有了那麽丁點的認識。現在就帶著之前的那些問題,正式的邁入對“T4模板

【思庫教育】2017PHP項目實戰基礎+進階+項目基礎

商品 資源庫 商城 文件引入 正則表達式 匿名 header 類和對象 多少 下載鏈接: 【思庫教育】2017PHP項目實戰基礎+進階+項目之基礎篇 小白變大牛,您的專屬資源庫! 小白變大牛,您的專屬資源庫! 內容非常充實,可以看目錄,設計的面多,項目多,技能多

Java程序員面試題JavaSE基礎

JavaSE一、JavaSE之基礎篇 1、JavaSE基礎之語法 ######(1)、簡述你對JVM,JRE,JDK的理解? JVM:java虛擬機。是一個模擬的計算機,相當於真實存在的計算機(軟件+硬件)。 JDK:是整個java的核心。程序員的產品。包括了java的運行環境、java的工具、java的

漫談Java IO基礎

等待 明顯 分發 限制 以及 經典 內核 很大的 lec Java的網絡編程如果不是專門搞服務器性能開發或者消息分發,幾乎可能涉及不到。但是它卻是面試找工作必問的一個知識點,涵蓋的知識體系也非常廣泛,從Java底層IO原理到操作系統內核組成,再到網絡TCP、UDP、HTT

python學習基礎

學習 功能 linu 輸出 程序 語言 記錄 自己的 mat python是一種實際應用較為廣泛的語言,並且python的使用是完全免費的,python是一種面向對象(oop)的語言,類模塊支持多繼承,多態等。筆者認為python最強大之處是可以靈活調用其他語言的程序為其所

PostMan工具使用基礎

p s 安裝包 soap 瀏覽器插件 www. align class lin 什麽是 PostMan工具使用之基礎篇 一.什麽是PostMan Postman一款非常流行的API調試工具。(其他測試工具 Jmeter、soapUI) 二.下載及安裝: 1.下載:

Java 8 基礎

1. lambda表示式 從java8出現以來lambda,也可稱為閉包(closure),是最重要的特性之一,它可以讓我們用簡潔流暢的程式碼完成一個功能。 很長一段時間java被吐槽是冗餘和缺乏函數語言程式設計能力的語言,隨著函數語言程式設計的流行java8種也引入了這種程式設計風

Java面試基礎(上)

題目來源於網路 後面是筆者自己提供的答案,僅供參考,如有錯誤,歡迎指正   一、基礎篇 1.1、Java基礎  面向物件的特徵:繼承、封裝和多型 final, finally, finalize 的區別 Exception、Er

JAVA網路通訊基礎

一、Socket套接字 作為JAVA網路通訊的基礎,Socket幫助程序實現程序間的建立連線並相互通訊。而Socket又分為客戶端和服務端,也就是Socket和SocketServer。在JAVA開發過程中,採用Socket套接字開發是較為簡便的。 1、SocketS

機器學習基礎

“”" @theme tuple @time 2018/11/26 @author lz “”" s1=(12,23,12,23,12,12) s2=(“lisi”,14,34) print(s1.index(12)) print(s1[0])#取值 print(s1+s2)#元祖連線

深度學習:Keras入門(一)基礎

1.關於Keras         1)簡介                    Keras是由純python編寫的基於theano/tensorflow的深度學習框架。          Keras是一個高層神經網路API,支援快速實驗,能夠把你的idea迅速轉換為

Kears入門基礎

本文轉載自http://www.cnblogs.com/lc1217/p/7132364.html 1.關於Keras         1)簡介               &n