日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用

發(fā)布時(shí)間:2023/12/10 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前面幾篇文章學(xué)習(xí)了鏈接器相關(guān)的內(nèi)容。現(xiàn)在開始來(lái)學(xué)習(xí)GDB調(diào)試。我們的目的是通過(guò)這幾篇文章將GDB調(diào)試完全學(xué)會(huì)。

文章目錄

  • 1 為什么需要GDB
  • 2 GDB 的常規(guī)應(yīng)用
  • 3 GDB調(diào)試程序?qū)嵗?/li>
  • 4 總結(jié)

1 為什么需要GDB

  • 什么是GDB?
  • GNU項(xiàng)目中的調(diào)試器(gnu debuger)
  • 能夠跟蹤程序的執(zhí)行,也能夠恢復(fù)程序執(zhí)行前的狀態(tài)
  • 為什么需要GDB?
  • 軟件不是一次性開發(fā)完的,是軟件就一定有bug,所以需要調(diào)試工具來(lái)定位bug
  • 調(diào)試是軟件開發(fā)過(guò)程中不可或缺的部分

2 GDB 的常規(guī)應(yīng)用

  • 自定義程序啟動(dòng)的方式(指定影響程序運(yùn)行的參數(shù))
  • 設(shè)置條件斷點(diǎn)(在條件滿足時(shí)暫停程序的執(zhí)行,一般為循環(huán)中的語(yǔ)句或者遞歸調(diào)用中的語(yǔ)句)
  • 回溯檢查導(dǎo)致程序異常的原因(一般是通過(guò)分析核心轉(zhuǎn)儲(chǔ)文件-core文件)
  • 動(dòng)態(tài)改變程序執(zhí)行流(定位問(wèn)題的輔助方式)

GDB的啟動(dòng)方式有哪些?

  • 直接啟動(dòng)
  • gdb
  • gdb test.out
  • gdb test.out core
  • 動(dòng)態(tài)連接
  • gdb test.out pid
  • 在給出gdb具體的調(diào)試代碼步驟之前,我們先來(lái)看看兩個(gè)應(yīng)用示例:

    • GDB應(yīng)用示例一

    • 其中設(shè)置命令行參數(shù)這里,如果了解main函數(shù)的參數(shù)的話應(yīng)該知道,如果不了解命令行參數(shù),請(qǐng)參考這篇文章: main函數(shù)參數(shù)的意義
    • 還有一點(diǎn)就是下面兩種載入目標(biāo)程序的命令是一樣的效果
    • 其他的用法都很好理解,我們不再贅述
    • GDB應(yīng)用示例二
    • 上述各個(gè)命令的使用方法也很好理解,我們只需要注意下圖中的兩種啟動(dòng)方式同樣是等效的:

    3 GDB調(diào)試程序?qū)嵗?/h1>

    下面就開始使用具體的例子來(lái)詳細(xì)解讀GDB調(diào)試的過(guò)程

    我們調(diào)試的兩個(gè)代碼為:

    • test.c
    #include <stdio.h> #include <unistd.h>extern int* g_pointer; // 外部變量 extern void func(); // 外部函數(shù)void test_1() {printf("test_1() : %p\n", test_1); }void test_2() {printf("test_2() : %p\n", test_2); }void test_3() {printf("test_3() : %p\n", test_3); }int main(int argc, char *argv[]) {typedef void(TFunc)();TFunc* fa[] = {test_1, test_2, test_3};int i = 0;printf("main() : begin...\n");for(i=0; i<argc; i++) //argc代表命令行參數(shù)的個(gè)數(shù){printf("argv[%d] = %s\n", i, argv[i]);}for(i=0; i<100; i++){fa[i%3]();sleep(argc > 1); // 如果argc大于1,則執(zhí)行睡眠函數(shù)}printf("g_pointer = %p\n", g_pointer);func();printf("main() : end...\n");return 0; }
    • func.c
    #include <stdio.h>int* g_pointer;void func() {*g_pointer = (int)"D.T.Software"; //注意,這里是出錯(cuò)的地方,g_pointer是指向0地址,但是在這里卻對(duì)0地址賦值return; }
    • GDB使用初探-----下面我們暫時(shí)先不調(diào)試,先熟悉熟悉幾個(gè)命令是如何使用的。
    • 首先對(duì)上述程序編譯并且運(yùn)行:
    • gcc func.c test.c -o test.out
    • ./test.out
    • 毫無(wú)疑問(wèn),程序肯定會(huì)產(chǎn)生錯(cuò)誤,如下圖:
    • 這是在意料之中的,畢竟在func.c程序中,我們對(duì)0地址進(jìn)行寫內(nèi)容了。
    • 那么現(xiàn)在我們開始使用gdb來(lái)定位出錯(cuò)誤,在開啟gdb調(diào)試之前,需要在編譯源程序的時(shí)候加上-g選項(xiàng),并將程序的崩潰信息轉(zhuǎn)儲(chǔ)的core文件(這在【軟件開發(fā)底層知識(shí)修煉】六 Binutils輔助工具之- addr2line與strip工具這篇文章中有講解過(guò))。
    • gcc -g test.c func.c -o test.out //重新編譯加上調(diào)試信息
    • ulimit -c unlimited //讓程序在崩潰時(shí)產(chǎn)生core文件
    • ./test.out //重新運(yùn)行看看是否產(chǎn)生core文件
    • 很明顯核心已轉(zhuǎn)出,生成了core文件----注意,這是GDB調(diào)試需要用的文件
  • 輸入命令:gdb test.out core 進(jìn)行調(diào)試:
    • 從這里我們甚至都直接看到了產(chǎn)生段錯(cuò)誤的地方就在func.c程序中的第7行,func函數(shù)中出的問(wèn)題。
    • 輸入quit命令退出當(dāng)前gdb調(diào)試
  • 輸入命令:gdb 進(jìn)行調(diào)試:
    • 輸入gdb后再gdb調(diào)試模式下輸入:file test.out
    • 然后字gdb調(diào)試模式下輸入run,顯示結(jié)果最后部分如下:
    • 通過(guò)上面的動(dòng)態(tài)圖我們很容易發(fā)現(xiàn),程序執(zhí)行的很快,瞬間就到了段錯(cuò)誤那里。我們回到test.c程序中,會(huì)發(fā)現(xiàn)這段代碼中:
      for(i=0; i<100; i++)
      {
      fa[i%3] ();
      sleep(argc > 1); // 如果argc大于1,則執(zhí)行睡眠函數(shù)
      }
      由于sleep參數(shù)中argc的參數(shù)為1(只有./test.out這個(gè)參數(shù)),所以不會(huì)睡眠。
    • 但是我們可以在gdb中進(jìn)行設(shè)置參數(shù),輸入命令set args D.T.SoftWare:
    • 就像下面的動(dòng)態(tài)圖一樣:
    • 很明顯,我們的程序運(yùn)行起來(lái)變得慢很多,這是因?yàn)槲覀兗恿艘粋€(gè)命令行參數(shù)D.T.SoftWare,現(xiàn)在命令行參數(shù)就有兩個(gè),一個(gè)是可執(zhí)行程序test.out,一個(gè)是D.T.SoftWare(如果這里不明白命令行參數(shù)的意思,請(qǐng)參考這篇文章:main函數(shù)參數(shù))
    • 最后,輸入ctrl + c可以終止程序的執(zhí)行,再輸入continue可以繼續(xù)執(zhí)行剛剛被終止的程序。
  • gdb動(dòng)態(tài)連接到一個(gè)正在執(zhí)行的程序,然后對(duì)其進(jìn)行調(diào)試
    • 還是直接看下面的動(dòng)圖,更加好理解:
    • 在右邊的終端我們運(yùn)行程序的時(shí)候加一個(gè)參數(shù)D.T.SoftWare這樣可以讓上述的for循環(huán)中的sleep開啟,讓程序執(zhí)行的慢一點(diǎn)
    • 程序執(zhí)行起來(lái)后,在左邊的終端首先輸入ps aux查看我們的程序的pid
    • 然后sudo gdb 開啟gdb,這里加上sudo以root模式開啟,是因?yàn)閯?dòng)態(tài)連接正在運(yùn)行的程序的話就需要以root模式
    • 開啟gdb進(jìn)入gdb模式后,使用attach pid (這里的pid根據(jù)你自己查到的pid寫)連接到我們運(yùn)行的程序。
    • 在我們連接到程序的一瞬間,發(fā)現(xiàn)程序的執(zhí)行停止了(使用continue可以繼續(xù)程序的執(zhí)行,當(dāng)程序運(yùn)行到段錯(cuò)誤那里,gdb可以發(fā)現(xiàn)錯(cuò)誤),說(shuō)明已經(jīng)連接到運(yùn)行中的程序,現(xiàn)在可以使用gdb對(duì)它進(jìn)行調(diào)試了。怎么調(diào)試隨你意,上面我們也說(shuō)了幾種簡(jiǎn)單的調(diào)試方法。

    4 總結(jié)

    本文只是介紹GDB調(diào)試的幾種簡(jiǎn)單用法。下一篇文章會(huì)學(xué)習(xí)GDB的斷點(diǎn)調(diào)試。

    本文章參考狄泰軟件學(xué)院相關(guān)課程
    想學(xué)習(xí)的可以加狄泰軟件學(xué)院群,
    群聊號(hào)碼:199546072

    學(xué)習(xí)探討加個(gè)人(可以免費(fèi)幫忙下載CSDN資源):
    qq:1126137994
    微信:liu1126137994

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。