【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

?一、 linux調(diào)試器 – gdb?1. gdb是什么

gdb 是 gnu 項目開發(fā)的一個命令行源代碼級調(diào)試器。它是 #%#$#%@%@%$#%$#%#%#$%@_e206a54e97690c++e50cc872dd70ee896 和其他類 unix 系統(tǒng)(如 macos,bsd)上 c、c++rust、go、fortran 等編程語言開發(fā)的標(biāo)準(zhǔn)調(diào)試工具。簡單來說,gdb 允許你深入正在運行的程序內(nèi)部:

1??啟動程序: 在受控環(huán)境下運行你的程序。2??暫停執(zhí)行: 在特定點(斷點)或發(fā)生特定事件(如信號)時停止程序。3??檢查狀態(tài): 當(dāng)程序暫停時,你可以查看: 變量的值(局部變量全局變量)。 程序執(zhí)行到了哪一行源代碼。 函數(shù)調(diào)用(backtrace)。 寄存器的內(nèi)容。 內(nèi)存區(qū)域的內(nèi)容。4??控制執(zhí)行: 在暫停點之后,你可以: 單步執(zhí)行代碼(逐行 step 或逐過程 next)。 繼續(xù)執(zhí)行直到下一個斷點或程序結(jié)束 continue。 跳入函數(shù)調(diào)用 step 或跳過函數(shù)調(diào)用 next。 跳出當(dāng)前函數(shù) finish。 甚至在運行時修改變量的值(小心使用?。?。5??分析崩潰: 當(dāng)程序崩潰(如段錯誤 Segmentation Fault)時,GDB 可以加載產(chǎn)生的 core dump 文件,讓你查看程序崩潰時的狀態(tài)(調(diào)用棧、變量值等),極大地方便了事后分析。

總結(jié)的說就是和VS環(huán)境中進(jìn)行調(diào)試是一樣的效果,只不過操作不同罷了

?2. gdb的使用更改發(fā)行版本:

默認(rèn)情況下我們在Linux上是無法進(jìn)行調(diào)試的,因為gcc/g++默認(rèn)生成的可執(zhí)行是release版本的

那么如何更改Linux下的發(fā)行版本?

gcc test.c -o testdebug -g

只需在gcc編譯時后面加入-g即可

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

使用指令

readelf -S XXXX(可執(zhí)行文件名稱)

就可以查看Linux下可執(zhí)行程序二進(jìn)制代碼的一些信息。elf就是Linux下的可執(zhí)行文件格式形式,可以觀察到,debug版本里面多了一些調(diào)試信息

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

調(diào)試階段:

我們將以下述代碼為例進(jìn)行調(diào)試:

代碼語言:JavaScript代碼運行次數(shù):0運行復(fù)制

  1 #include<stdio.h>  2   3   4 int Add(int left, int right)  5 {  6     return left + right;  7 }  8   9 int main() 10 { 11     int sum = Add(10, 20); 12     printf("sum = %d ", sum);                                                                                                                            13     printf("hello gdba "); 14     printf("hello gdbb "); 15     printf("hello gdbc "); 16     printf("hello gdbd "); 17     printf("hello gdbe "); 18     printf("hello gdbf "); 19     printf("hello gdbg "); 20     printf("hello gdbh "); 21     printf("hello gdbi "); 22     printf("hello gdbj "); 23     return 0; 24 }

1??進(jìn)入調(diào)試模式使用指令gdb XXX(調(diào)試版本可執(zhí)行)

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

2??顯示代碼指令:l l + n(行號):從第n行開始顯示

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

3??斷點相關(guān)指令break 行號:在某一行設(shè)置斷點。b 行號即可break 函數(shù)名:在某個函數(shù)開頭設(shè)置斷點 info break :查看斷點信息。info b即可delete 斷電的編號:刪除斷點。d 編號即可

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序
【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

4??調(diào)試運行 r:運行,有斷點會在第一個斷點處停下,無斷點直接運行結(jié)束c:運行至下一個斷點處結(jié)束

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序
【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

n:逐過程,即在調(diào)用函數(shù)處不進(jìn)入函數(shù)內(nèi)部s:逐語句,在調(diào)用函數(shù)處進(jìn)入函數(shù)內(nèi)

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序
【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序
【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

5??顯示變量breaktrace(或bt):查看各級函數(shù)調(diào)用堆棧p 變量:打印變量值。(該指令只會顯示一次,不會隨著程序的執(zhí)行而變動)display 變量:常顯示變量,會類似VS環(huán)境中隨著程序的變動而改變undisplay 變量編號:將常顯示變量取消

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序
【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

6??其它指令finish:執(zhí)行到當(dāng)前函數(shù)返回,然后停下來等待命令(這個指令可以讓我們?nèi)ヅ袛噱e誤具體出現(xiàn)在那個函數(shù))until:跳轉(zhuǎn)到指定行,并且前面程序均已執(zhí)行

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序
【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

7??退出調(diào)試模式指令 quit:退出gdb。q即可

總結(jié):

上面的指令都了解的話,用起來gdb已經(jīng)沒啥大問題了,下面把常見的一些gdb指令總結(jié)一下,如果再后續(xù)的使用過程中用到了,大家回來查閱即可。

list/l 行號:顯示binFile源代碼,接著上次的位置往下列,每次列10行。list/l 函數(shù)名:列出某個函數(shù)的源代碼。r或run:運行程序。n 或 next:單條執(zhí)行。s或step:進(jìn)入函數(shù)調(diào)用break(b) 行號:在某一行設(shè)置斷點break 函數(shù)名:在某個函數(shù)開頭設(shè)置斷點info break :查看斷點信息。finish:執(zhí)行到當(dāng)前函數(shù)返回,然后挺下來等待命令print(p):打印表達(dá)式的值,通過表達(dá)式可以修改變量的值或者調(diào)用函數(shù) p 變量:打印變量值。set var:修改變量的值continue(或c):從當(dāng)前位置開始連續(xù)而非單步執(zhí)行程序run(或r):從開始連續(xù)而非單步執(zhí)行程序delete breakpoints:刪除所有斷點delete breakpoints n:刪除序號為n的斷點disable breakpoints:禁用斷點enable breakpoints:啟用斷點info(或i) breakpoints:參看當(dāng)前設(shè)置了哪些斷點display 變量名:跟蹤查看一個變量,每次停下來都顯示它的值undisplay:取消對先前設(shè)置的那些變量的跟蹤until X行號:跳至X行breaktrace(或bt):查看各級函數(shù)調(diào)用及參數(shù)info(i) locals:查看當(dāng)前棧幀局部變量的值quit:退出gdb?二、Linux下第一條程序-進(jìn)度條?1. 背景知識:

先看一段代碼:

代碼語言:javascript代碼運行次數(shù):0運行復(fù)制

#include<stdio.h>#include<unistd.h>int main(){    printf("這是一個試驗程序");    sleep(3);                                                                                                                                                return 0;}

運行之后,會發(fā)現(xiàn),printf竟然沒有打印,而是停了3秒之后才出現(xiàn),相信你會說,你自己sleep了3秒,能怪人家不出現(xiàn)?請看下述代碼:

代碼語言:javascript代碼運行次數(shù):0運行復(fù)制

printf("這是一個試驗程序 "); 

如果在printf加了回車換行,你會驚奇的發(fā)現(xiàn),printf先打印,然后休眠了3秒之后代碼才結(jié)束,這是為何?好,知識點來了。

知識點1:

首先針對于沒有回車換行,為什么沒有?

是因為此時printf所要打印的內(nèi)容,儲存在了緩沖區(qū),而有了 為什么就有了呢?

這涉及到了標(biāo)準(zhǔn)輸出(stdout)的緩沖機制,如下:

緩沖機制類型

行緩沖(Line-buffered):遇到換行符 時自動刷新緩沖區(qū)(立即輸出內(nèi)容)。 全緩沖(Fully-buffered):緩沖區(qū)滿或顯式刷新時才輸出。 無緩沖(Unbuffered):立即輸出(如 stderr)。

而終端環(huán)境下的 stdout 默認(rèn)是行緩沖

因此兩段代碼的具體解釋如下:

代碼語言:javascript代碼運行次數(shù):0運行復(fù)制

printf("這是一個試驗程序 ");  // 末尾有換行符sleep(3);

觸發(fā)刷新:換行符使緩沖區(qū)立即刷新,內(nèi)容立刻顯示在終端。 后續(xù)休眠:之后程序休眠 3 秒,用戶先看到輸出,再等待。 代碼語言:javascript代碼運行次數(shù):0運行復(fù)制

printf("這是一個試驗程序");  // 無換行符sleep(3);

緩沖區(qū)未刷新:輸出內(nèi)容暫存于內(nèi)存緩沖區(qū)(未滿且未遇到 )。 先休眠 3 秒:程序進(jìn)入休眠,此時終端無輸出。 程序結(jié)束時刷新:main 函數(shù)返回前,自動刷新所有緩沖區(qū),內(nèi)容在休眠結(jié)束后顯示。

所以也就是說終端環(huán)境下stdout是行緩沖, 有刷新行緩沖區(qū)的功效,是!怎么證明?如下:

代碼語言:javascript代碼運行次數(shù):0運行復(fù)制

int main(){    printf("這是一個試驗程序");    fflush(stdout);                                                                                                                                          sleep(3);                                                                                                                   return 0;                                                                                                               }                                                                                                                           

fflush是刷新緩沖區(qū)的,此時你便會看到,先打印結(jié)果,再休眠3秒,關(guān)于緩沖區(qū)的具體知識,在我們學(xué)習(xí)到Linux后面的時候就會明白

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

對于上述回車換行,我們見下一段代碼:

代碼語言:javascript代碼運行次數(shù):0運行復(fù)制

int main(){    int cnt = 10;    while(cnt)    {        printf("這是一個倒計時:%2d ", cnt);        fflush(stdout);        cnt--;                                                                                                                                          sleep(1);    }    return 0;}

/r就是回車的作用,但是它沒有刷新緩沖區(qū)的功能,所以我們每次要進(jìn)行刷新緩沖區(qū)才能看到一個正常的倒計時,如下:

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

?2. 進(jìn)度條程序

有了前面的知識鋪墊,我們就可以寫一個Linux下第一條小程序進(jìn)度條如下所示:

【Linux】想學(xué)習(xí)Linux不看這一篇你就慢了–>工具篇(四)gdb、進(jìn)度條程序

首先,需要101個字符數(shù)組,因為最后一個需要放‘

久久国产精品成人免费| 久久天天婷婷五月俺也去| 熟妇人妻久久中文字幕| 午夜精品久久久久久99热| 久久久久久久人妻无码中文字幕爆| 久久天天躁狠狠躁夜夜96流白浆| 久久夜色精品国产网站| 国产毛片久久久久久国产毛片| 亚洲а∨天堂久久精品9966| 亚洲级αV无码毛片久久精品| 青青热久久综合网伊人| 一极黄色视频久久网站| 国产精品久久久久久影院| 亚洲国产成人久久综合野外| 日韩精品久久久久久免费| 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 久久久久久夜精品精品免费啦| 97久久超碰成人精品网站| 久久人人爽人人澡人人高潮AV | 久久久综合香蕉尹人综合网| 麻豆亚洲AV永久无码精品久久| 国产午夜精品久久久久九九电影| 伊人久久大香线蕉综合Av| 激情综合色综合久久综合| 国内精品久久久久影院日本 | 无码乱码观看精品久久| 日韩精品国产自在久久现线拍 | 色偷偷91久久综合噜噜噜噜| 精品午夜久久福利大片| 久久不见久久见免费视频7| 精品久久久一二三区| 久久婷婷五月综合色99啪ak| 热久久这里只有精品| 久久综合久久综合久久综合| 国产精品99精品久久免费| 色综合久久中文字幕无码| 久久久精品国产免大香伊 | 99久久免费国产特黄| 99精品久久精品一区二区| 久久91精品国产91久久户| 久久精品一本到99热免费|