gdb好文章:GDB十分鐘教程

(GUI調試器:insightddd


  • list(l) :其作用就是列出程序的源代碼,默認每次顯示10行。
  • list 行號:將顯示當前文件以“行號”為中心的前后10行代碼,如:list 12
  • list 行號1,行號2: 將顯示行號1與行號2之間的代碼
  • list 函數名:將顯示“函數名”所在函數的源代碼,如:list main
  • list :不帶參數,將接著上一次 list 命令的,輸出后續的代碼。

  • set args:設置運行程序時的命令行參數,如:set args 33 55
  • show args:顯示命令行參數
  • break(b):為程序設置斷點。
    • break 行號:在當前文件的“行號”處設置斷點,如:break? 33,
    • break filename:line-number:在指定文件的指定行設置斷點
    • break 函數名:在用戶定義的函數“函數名”處設置斷點,如:break cb_button
    • info b number1,number2 …… 顯示指定斷點信息;info b (顯示所有斷點信息)?
    • disable b Num:關閉斷點“Num”,使其無效,其中“Num”為 info breakpoints 中顯示的對應值;?disable b(禁用所有斷點)
    • enable b Num:打開斷點“Num”,使其重新生效;?enable b (啟用所有斷點)
    • clear linenumber:清除指定行上的所有斷點

  • until:當你厭倦了在一個循環體內單步跟蹤時,這個命令可以運行程序直到退出循環體。
  • backtrace(bt) ,where:顯示當前程序的函數調用堆棧。
  • watch 表達式:設置一個監視點,一旦被監視的“表達式”的值改變,gdb將強行終止正在被調試的程序。如: watch a
  • layout:用于分割窗口,可以一邊查看代碼,一邊測試:
    • layout src:顯示源代碼窗口
    • layout asm:顯示反匯編窗口
    • layout regs:顯示源代碼/反匯編和CPU寄存器窗口
    • layout split:顯示源代碼和反匯編窗口
    • Ctrl + L:刷新窗口
    set variable=value:將值賦予變量

本文寫給主要工作在Windows操作系統下而又需要開發一些跨平臺軟件的程序員朋友,以及程序愛好者。

GDB是一個由GNU開源組織發布的、UNIX/LINUX操作系統下的、基于命令行的、功能強大的程序調試工具。

GDB中的命令固然很多,但我們只需掌握其中十個左右的命令,就大致可以完成日常的基本的程序調試工作。

?命令?解釋?示例
file <文件名>加載被調試的可執行程序文件。
因為一般都在被調試程序所在目錄下執行GDB,因而文本名不需要帶路徑。
(gdb) file gdb-sample
rrun的簡寫,運行被調試的程序。
如果此前沒有下過斷點,則執行完整個程序;如果有斷點,則程序暫停在第一個可用斷點處。
(gdb) r
ccontinue的簡寫,繼續執行被調試程序,直至下一個斷點或程序結束。(gdb) c
b <行號>
b <函數名稱>
b *<函數名稱>
b *<代碼地址>

d [編號]

b: break的簡寫,設置斷點。兩可以使用“行號” “函數名稱” “執行地址”等方式指定斷點位置。
其中在函數名稱前面加“*”符號表示將斷點設置在“由編譯器生成的prolog代碼處”。如果不了解匯編,可以不予理會此用法。

d: delete breakpoint的簡寫,刪除指定編號的某個斷點,或刪除所有斷點(d b)。斷點編號從1開始遞增。

(gdb) b 8
(gdb) b main
(gdb) b *main
(gdb) b *0x804835c

(gdb) d

s

finish

n

s: step的簡寫,執行一行源程序代碼,如果此行代碼中有函數調用,則進入該函數;
n: next的簡寫,執行一行源程序代碼,此行代碼中的函數調用也一并執行。

s 相當于其它調試器中的“Step Into (單步跟蹤進入)”;VS的F11

Step Out, VS的SHIFT+F11
n 相當于其它調試器中的“Step Over (單步跟蹤)”。VS的F10

這兩個命令必須在有源代碼調試信息的情況下才可以使用(GCC編譯時使用“-g”參數)。

(gdb) s
(gdb) n

si

ni

si命令類似于s命令,ni命令類似于n命令。所不同的是,這兩個命令(si/ni)所針對的是匯編指令,而s/n針對的是源代碼。(gdb) si
(gdb) ni
p <變量名稱>print的簡寫,顯示指定變量(臨時變量或全局變量)的值。(gdb) p i
(gdb) p nGlobalVar
display...

undisplay <編號>

display,設置程序中斷后欲顯示的數據及其格式。
例如,如果希望每次程序中斷后可以看到即將被執行的下一條匯編指令,可以使用命令
“display /i $pc”
其中 $pc 代表當前匯編指令,/i 表示以十六進行顯示。當需要關心匯編代碼時,此命令相當有用。

undispaly,取消先前的display設置,編號從1開始遞增。

(gdb) display /i $pc

(gdb) undisplay 1

iinfo的簡寫,用于顯示各類信息,詳情請查閱“help i”。(gdb) i r
qquit的簡寫,退出GDB調試環境。(gdb) q
help [命令名稱]GDB幫助命令,提供對GDB名種命令的解釋說明。
如果指定了“命令名稱”參數,則顯示該命令的詳細說明;如果沒有指定參數,則分類顯示所有GDB命令,供用戶進一步瀏覽和查詢。
(gdb) help display

 

廢話不多說,下面開始實踐。

先給出一個示例用的小程序,C語言代碼,簡單的不能再簡單了:

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

//此程序僅作為“GDB十分鐘教程”的示例代碼
//Email:

//blog:?
//WebSite:


#include?
<stdio.h>

int
?nGlobalVar?=?0;

int
?tempFunction(int?a,?int?b)
{
????printf("tempFunction is called, a = %d, b = %d \n",?a,?b
);
????return?(a?+?b
);
}


int
?main()
{
????int?n
;
??? n?=?1
;
??? n
++;
??? n
--;

??? nGlobalVar?+=?100
;
??? nGlobalVar?-=?12
;

????printf("n = %d, nGlobalVar = %d \n",?n,?nGlobalVar
);

??? n?=?tempFunction(1,?2
);
????printf("n = %d",?n
);

????return?0
;
}

請將此代碼復制出來并保存到文件 gdb-sample.c 中,然后切換到此文件所在目錄,用GCC編譯之:

gcc gdb-sample.c -o gdb-sample -g

在上面的命令行中,使用 -o 參數指定了編譯生成的可執行文件名為 gdb-sample,使用參數 -g 表示將源代碼信息編譯到可執行文件中。如果不使用參數 -g,會給后面的GDB調試造成不便。當然,如果我們沒有程序的源代碼,自然也無從使用 -g 參數,調試/跟蹤時也只能是匯編代碼級別的調試/跟蹤。

下面“gdb”命令啟動GDB,將首先顯示GDB說明,不管它:

GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
(gdb)?

上面最后一行“(gdb) ”為GDB內部命令引導符,等待用戶輸入GDB命令。

下面使用“file”命令載入被調試程序 gdb-sample(這里的 gdb-sample 即前面 GCC 編譯輸出的可執行文件):

(gdb) file gdb-sample
Reading symbols from gdb-sample...done.

上面最后一行提示已經加載成功。

下面使用“r”命令執行(Run)被調試文件,因為尚未設置任何斷點,將直接執行到程序結束:

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample
n = 1, nGlobalVar = 88
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

下面使用“b”命令在 main 函數開頭設置一個斷點(Breakpoint):

(gdb) b main
Breakpoint 1 at 0x804835c: file gdb-sample.c, line 19.

上面最后一行提示已經成功設置斷點,并給出了該斷點信息:在源文件 gdb-sample.c 第19行處設置斷點;這是本程序的第一個斷點(序號為1);斷點處的代碼地址為 0x804835c(此值可能僅在本次調試過程中有效)。回過頭去看源代碼,第19行中的代碼為“n = 1”,恰好是 main 函數中的第一個可執行語句(前面的“int n;”為變量定義語句,并非可執行語句)。

再次使用“r”命令執行(Run)被調試程序:

(gdb) r
Starting program: /home/liigo/temp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;

程序中斷在gdb-sample.c第19行處,即main函數是第一個可執行語句處。

上面最后一行信息為:下一條將要執行的源代碼為“n = 1;”,它是源代碼文件gdb-sample.c中的第19行。

下面使用“s”命令(Step)執行下一行代碼(即第19行“n = 1;”):

(gdb) s
20 n++;

上面的信息表示已經執行完“n = 1;”,并顯示下一條要執行的代碼為第20行的“n++;”。

既然已經執行了“n = 1;”,即給變量 n 賦值為 1,那我們用“p”命令(Print)看一下變量 n 的值是不是 1 :

(gdb) p n
$1 = 1

果然是 1。($1大致是表示這是第一次使用“p”命令——再次執行“p n”將顯示“$2 = 1”——此信息應該沒有什么用處。)

下面我們分別在第26行、tempFunction 函數開頭各設置一個斷點(分別使用命令“b 26”“b tempFunction”):

(gdb) b 26
Breakpoint 2 at 0x804837b: file gdb-sample.c, line 26.
(gdb) b tempFunction
Breakpoint 3 at 0x804832e: file gdb-sample.c, line 12.

使用“c”命令繼續(Continue)執行被調試程序,程序將中斷在第二個斷點(26行),此時全局變量 nGlobalVar 的值應該是 88;再一次執行“c”命令,程序將中斷于第三個斷點(12行,tempFunction 函數開頭處),此時tempFunction 函數的兩個參數 a、b 的值應分別是 1 和 2:

(gdb) c
Continuing.

Breakpoint 2, main () at gdb-sample.c:26
26 printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);
(gdb) p nGlobalVar
$2 = 88
(gdb) c
Continuing.
n = 1, nGlobalVar = 88

Breakpoint 3, tempFunction (a=1, b=2) at gdb-sample.c:12
12 printf("tempFunction is called, a = %d, b = %d /n", a, b);
(gdb) p a
$3 = 1
(gdb) p b
$4 = 2

上面反饋的信息一切都在我們預料之中,哈哈~~~

再一次執行“c”命令(Continue),因為后面再也沒有其它斷點,程序將一直執行到結束:

(gdb) c
Continuing.
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

 

有時候需要看到編譯器生成的匯編代碼,以進行匯編級的調試或跟蹤,又該如何操作呢?

這就要用到display命令“display /i $pc”了(此命令前面已有詳細解釋):

(gdb) display /i $pc
(gdb)?

此后程序再中斷時,就可以顯示出匯編代碼了:

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

看到了匯編代碼,“n = 1;”對應的匯編代碼是“movl $0x1,0xfffffffc(%ebp)”。

并且以后程序每次中斷都將顯示下一條匯編指定(“si”命令用于執行一條匯編代碼——區別于“s”執行一行C代碼):

(gdb) si
20 n++;
1: x/i $pc 0x8048363 <main+23>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x08048366 20 n++;
1: x/i $pc 0x8048366 <main+26>: incl (%eax)
(gdb) si
21 n--;
1: x/i $pc 0x8048368 <main+28>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x0804836b 21 n--;
1: x/i $pc 0x804836b <main+31>: decl (%eax)
(gdb) si
23 nGlobalVar += 100;
1: x/i $pc 0x804836d <main+33>: addl $0x64,0x80494fc

 

接下來我們試一下命令“b *<函數名稱>”。

為了更簡明,有必要先刪除目前所有斷點(使用“d”命令——Delete breakpoint):

(gdb) d
Delete all breakpoints? (y or n) y
(gdb)

當被詢問是否刪除所有斷點時,輸入“y”并按回車鍵即可。

下面使用命令“b *main”在 main 函數的 prolog 代碼處設置斷點(prolog、epilog,分別表示編譯器在每個函數的開頭和結尾自行插入的代碼):

(gdb) b *main
Breakpoint 4 at 0x804834c: file gdb-sample.c, line 17.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 4, main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834c <main>: push %ebp
(gdb) si
0x0804834d 17 {
1: x/i $pc 0x804834d <main+1>: mov %esp,%ebp
(gdb) si
0x0804834f in main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834f <main+3>: sub $0x8,%esp
(gdb) si
0x08048352 17 {
1: x/i $pc 0x8048352 <main+6>: and $0xfffffff0,%esp
(gdb) si
0x08048355 17 {
1: x/i $pc 0x8048355 <main+9>: mov $0x0,%eax
(gdb) si
0x0804835a 17 {
1: x/i $pc 0x804835a <main+14>: sub %eax,%esp
(gdb) si
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

此時可以使用“i r”命令顯示寄存器中的當前值———“i r”即“Infomation Register”:

(gdb) i r
eax 0xbffff6a4 -1073744220
ecx 0x42015554 1107383636
edx 0x40016bc8 1073834952
ebx 0x42130a14 1108544020
esp 0xbffff6a0 0xbffff6a0
ebp 0xbffff6a8 0xbffff6a8
esi 0x40015360 1073828704
edi 0x80483f0 134513648
eip 0x8048366 0x8048366
eflags 0x386 902
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x33 51

當然也可以顯示任意一個指定的寄存器值:

(gdb) i r eax
eax 0xbffff6a4 -1073744220

 

最后一個要介紹的命令是“q”,退出(Quit)GDB調試環境:

(gdb) q
The program is running. Exit anyway? (y or n) y

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449480.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449480.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449480.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

機器學習預測+akshare

import pandas as pd import akshare as ak import numpy as np import talib from datetime import datetime, timedelta import time 獲取股票數據 from_date 2010-01-01 from_date datetime.strptime(from_date,"%Y-%m-%d") day_nums 1 current_dt time.st…

[python作業AI畢業設計博客]比Selenium IDE更好用的錄制工具: Katalon Recorder

Selenium IDE(集成開發環境 Integrated Development Environment)是用于構建測試腳本的原型工具。 它是一個Firefox插件&#xff0c;提供了易于使用的界面&#xff0c;用于開發自動化測試。 但是最新的Selenium IDE總是彈出一系列如下的對話框&#xff0c;不能直接錄制&#xf…

CentOS 7 : Docker私有倉庫搭建和使用

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 系統環境&#xff1a; CentOS 7.2 192.168.0.179&#xff1a;docker倉庫 192.168.0.60&#xff1a;客戶端 安裝并啟動docker yum -y…

價值投資/指標選股(akshare)

利用akshare的數據源&#xff0c;可以獲取所有的股票數據以及公開的財務數據&#xff0c;可以進行條件篩選&#xff0c;獲取滿足條件的股票。 這套模板可以用于價值投資&#xff0c;指標選股。選股周期為日線級別。然后結果可以郵箱發送。 import time import akshare as ak #…

gdb常用命令

[rootredhat home]#gdb 調試文件&#xff1a;啟動gdb (gdb) l &#xff1a;&#xff08;字母l&#xff09;從第一行開始列出源碼 (gdb) break n :在第n行處設置斷點 (gdb) break func&#xff1a;在函數func()的入口處設置斷點 (gdb) info break&#xff1a; 查看斷點信息 (gdb…

有前途的人工智能大數據分析相關職業:Python數據科學入門之路

2019獨角獸企業重金招聘Python工程師標準>>> 為什么學習Python數據科學&#xff1f; Python是數據科學職業所需的寶貴技能之一。Python是數據科學的首選編程語言。 2016年&#xff0c;它超越了R on Kaggle&#xff0c;這是數據科學競賽的首選平臺。2017年&#xff0…

遍歷Map key-value的兩種方法、遍歷Set方法

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 第一種遍歷方法 : 先獲取Map中的所有key值&#xff0c;然后根據key&#xff0c;依次從Map中去數據 Map<String,String> test…

STL 容器簡介:C++ 容器:順序性容器、關聯式容器和容器適配器

STL標準容器類簡介 標準容器類說明順序性容器vector從后面快速的插入與刪除&#xff0c;直接訪問任何元素deque從前面或后面快速的插入與刪除&#xff0c;直接訪問任何元素list雙鏈表&#xff0c;從任何地方快速插入與刪除關聯容器set快速查找&#xff0c;不允許重復值multise…

用友云開發者中心助你上云系列之在線調試

現在&#xff0c;大家開始越來越多的談論到高可用架構的互聯網應用。什么是高可用&#xff1f;高可用HA&#xff08;High Availability&#xff09;是分布式系統架構設計中必須考慮的因素之一&#xff0c;它通常是指&#xff0c;通過設計減少系統不能提供服務的時間。當我們談論…

python根據財務指標尋找價值股票

確定股票池 from concurrent.futures import ThreadPoolExecutor import urllib import os from time import sleep import pandas as pd # 上證代碼 shanghaicode [] for i in range(600000, 606000, 1):shanghaicode.append(str(i))# 深證代碼 shenzhencode [] for i in r…

WPF Bitmap轉BitmapSource,Image

//引用&#xff1a;using System.Windows.Interop; //Imagingusing System.Drawing; //Bitmap public static Imaging.BitmapSource ConvertToBitmapSource(Bitmap btmap) { return Imaging.CreateBitmapSourceFromHBitmap(btmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empt…

解決jboss.resteasy.spi.UnhandledException: Response is committed, can‘t handle exception

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff0c;如圖&#xff1a; 我的情況是&#xff1a;項目作壓測&#xff0c;這個接口請求量不大時是OK的 &#xff0c;當達到…

linux下如何做ghost,又簡單又方便,很實用的方法!!!

Linux 做ghost 使用指南。 轉載時請注明本博客地址。 1. 使用unetbootin-windows-585.exe 軟件做 ubuntu 的liveusb &#xff0c;一定是做liveusb&#xff0c;不是liveCD&#xff0c;如果你做的是liveCD&#xff0c;要把做好的文件拷出來&#xff0c;否則&#xff0c;重…

Webpack4: Tree-shaking 深度解析

什么是Tree-shaking 所謂Tree-shaking就是‘搖’的意思&#xff0c;作用是把項目中沒必要的模塊全部抖掉&#xff0c;用于在不同的模塊之間消除無用的代碼&#xff0c;可列為性能優化的范疇。 Tree-shaking早期由rollup實現&#xff0c;后來webpack2也實現了Tree-shaking的功能…

真格量化——GFTD策略

#!/usr/bin/env python # coding:utf-8 from PoboAPI import * import datetime import numpy as np import math#開始時間,用于初始化一些參數 def OnStart(context) :print "I\m starting..."#設置全局變量g.signalcount = 0 g.signal_list = []g.buysignal = 0 g…

解決org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql ...

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯如題&#xff1a; org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [id]…

Spring WebFlux 響應式編程學習筆記(一)

各位Javaer們&#xff0c;大家都在用SpringMVC吧&#xff1f;當我們不亦樂乎的用著SpringMVC框架的時候&#xff0c;Spring5.x又悄(da)無(zhang)聲(qi)息(gu)的推出了Spring WebFlux。web? 不是已經有SpringMVC這么好用的東西了么&#xff0c;為啥又冒出個WebFlux&#xff1f;…

Django Rest Framework -解析器

基本代碼結構 urls.py rom django.conf.urls import url, include from web.views.s5_parser import TestViewurlpatterns [url(rtest/, TestView.as_view(), nametest), ]views.py from rest_framework.views import APIView from rest_framework.response import Response f…

真格量化——菜粕策略

#!/usr/bin/env python # coding:utf-8 from PoboAPI import * import datetime import time import numpy as np from copy import *#開始時間,用于初始化一些參數 def OnStart(context) :context.myacc = None#登錄交易賬號if context.accounts["回測期貨"].Login…

PostgreSQL查看版本信息

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.查看客戶端版本 psql --version 1 2.查看服務器端版本 2.1 查看詳細信息 select version(); 1 2.2 查看版本信息 show server_ve…