C++霧中風(fēng)景番外篇3:GDB與Valgrind 铣口,調(diào)試代碼內(nèi)存的工具

寫 C++的同學(xué)想必有太多和內(nèi)存打交道的血淚經(jīng)驗(yàn)了,常常被 C++的內(nèi)存問題攪的焦頭爛額偶器。(寫 core 的經(jīng)驗(yàn)了)有很多同學(xué)一見到 core 就兩眼一抹黑斩萌,不知所措了。筆者 入""C++之后屏轰,在調(diào)試 C++代碼的過程之中颊郎,學(xué)習(xí)了不少調(diào)試代碼內(nèi)存的工具。希望借這個(gè)機(jī)會(huì)來介紹一下筆者常用的工具霎苗,GDB姆吭,Valgrind等等,相信大家通過好好運(yùn)用這些工具唁盏,能更好的馴服內(nèi)存這匹"野馬"内狸。

1.利用 GDB 調(diào)試 CoreDump

CoreDump時(shí)一個(gè)二進(jìn)制的文件,進(jìn)程發(fā)生錯(cuò)誤崩潰時(shí)厘擂,內(nèi)核會(huì)產(chǎn)生一個(gè)瞬時(shí)的快照答倡,記錄該進(jìn)程的內(nèi)存、運(yùn)行堆棧狀態(tài)等信息保存在core文件之中驴党。做個(gè)簡(jiǎn)單的類比,core 文件相當(dāng)于飛機(jī)運(yùn)行時(shí)的"黑匣子"获茬,能夠幫助我們更好的調(diào)試 C++程序的問題港庄。OK倔既,接下來筆者將介紹一下如果利用GDB 來調(diào)試 CoreDump的文件。

  • CoreDump 文件的大小

首先我們先確定一下操作系統(tǒng)是否會(huì)產(chǎn)生 CoreDump 文件鹏氧。通過ulimit -c獲取 core 文件的限制大胁秤俊:

查看 core 文件的大小限制

上面顯示筆者電腦的 core 文件的大小是0,我們需要調(diào)整一下把还。通過ulimit調(diào)整為無限制实蓬。當(dāng)然這種調(diào)整是臨時(shí)的,reboot 之后就恢復(fù)為0了吊履。

ulimit -c ulimited

如果需要永久修改安皱,可以通過/etc/security/limits.conf 來修改 core 文件的大小。

  • CoreDump 文件的生成路徑
    默認(rèn)情況下艇炎,core dump生成的文件名為core酌伊,而且就在程序當(dāng)前目錄下。通過修改/proc/sys/kernel/core_pattern可以控制core文件保存位置和文件格式缀踪。(建議將后綴改為進(jìn)程號(hào)) 筆者這里簡(jiǎn)單起見居砖,不進(jìn)行修改了。

  • 編寫core 代碼驴娃,這里筆者利用線程訪問了空指針

#include <unistd.h>
#include <thread>

void core() {
    char* ch = nullptr;
    *ch = 'a';
}

int main() {
    auto t1 = std::thread(core);
    sleep(5);
    return 0;
}
  • 編譯運(yùn)行該代碼奏候,產(chǎn)生段錯(cuò)誤,生成了 core 文件


    圖片.png
  • 利用 GDB 調(diào)試 core 文件
    調(diào)試 core 文件需要利用原生編譯出的二進(jìn)制文件調(diào)試唇敞。這里有一點(diǎn)需要注意的蔗草,如果編譯 C++文件之時(shí)沒有加-g的編譯選項(xiàng),core 文件的調(diào)試內(nèi)容會(huì)不夠完整厚棵。筆者這里建議開啟對(duì)應(yīng)的編譯選項(xiàng)蕉世,這會(huì)導(dǎo)致對(duì)應(yīng)的二進(jìn)制文件變大,編譯時(shí)間變長(zhǎng)婆硬。(生產(chǎn)環(huán)境可以考慮關(guān)閉)使用gdb 二進(jìn)制文件 core 文件打開 core 文件狠轻。

利用 gdb 調(diào)試 core 文件

core 文件列出了兩個(gè)線程的信息。我們需要判斷對(duì)應(yīng)的問題代碼的定位彬犯,接下來我們一起來梳理一下:
info thread查看線程的運(yùn)行情況向楼,在這里我們就可以判斷代碼 core 在什么線程之中了,如果還是無法確定谐区,可以通過thread apply all bt列出更加詳盡的堆棧信息湖蜕。

用 info thread 查看線程運(yùn)行情況

利用 thread apply all bt 顯示詳盡的堆棧信息

通過上述信息可以確認(rèn),thread 1的代碼存在問題宋列。我們通過thread 1切換到 thread 1昭抒,用bt顯示堆棧信息繼續(xù)追查:
Thread 1的堆棧信息

之后我們來看看令人生疑的棧內(nèi)容,這里顯然棧0是我們懷疑的代碼,用frame 1查看灭返。

對(duì)應(yīng)存在『?jiǎn)栴}』的語(yǔ)句

好了盗迟,這里我們找到了引起問題罪魁禍?zhǔn)椎拇a,訪問了空指針熙含。

小結(jié)

程序運(yùn)行的 core 文件是我們調(diào)試代碼十分重要依據(jù)罚缕,通過 GDB 可以很好的給出我們修改代碼的線索和參考,熟悉掌握GDB 的調(diào)試技巧怎静,能夠大大解放我們調(diào)試問題代碼的生產(chǎn)力邮弹。

2.利用Valgrind判斷內(nèi)存泄露

亡羊補(bǔ)牢不如未雨綢繆,與其等到出現(xiàn)程序崩潰時(shí)使用 GDB 來調(diào)試解決蚓聘,不如事前確認(rèn)代碼之中可能引發(fā)的問題腌乡。所以筆者接下來要介紹一款來自大不列顛的C++代碼分析神器:Valgrind。(Valgrind的作者也通過開發(fā)Valgrind獲得了第二屆Google-O'Reilly開源代碼大獎(jiǎng)~~~)
Valgrind 十分強(qiáng)大或粮,適用于內(nèi)存分析导饲,泄漏檢測(cè)、鎖分析氯材,性能評(píng)估渣锦。筆者也只掌握了一些基本的入門使用。希望這里能夠拋磚引玉氢哮,更多復(fù)雜的用法煩請(qǐng)參考官方文檔袋毙。

Valgrind的安裝

Valgrind的安裝很簡(jiǎn)單,筆者的發(fā)行版帶了對(duì)應(yīng)的 deb 包冗尤。通過 apt-get 的包管理工具就可以直接安裝了听盖,其他的發(fā)行版也可以作為參考。

sudo apt-get install valgrind
Valgrind的使用

與 GDB 類似裂七,Valgrind 同樣推薦使用-g作為編譯參數(shù)皆看。能夠更好的對(duì)代碼進(jìn)行分析。這里我們依舊使用之前的例子進(jìn)行測(cè)試:

valgrind ./untitiled

下面是 Valgrind 的分析結(jié)果:


valgrind 的分析結(jié)果

這里有顯示Invalid write of size 1背零,說明這里有一個(gè)不合法的寫入腰吟,并且寫入了1個(gè)字節(jié)的內(nèi)容。也就是指的是我們之前代碼之中寫入空指針的行為徙瓶。

接下來我們要展示 Valgrind更加強(qiáng)大的功能毛雇。它展示了程序的內(nèi)存使用情況,并且給出總結(jié):

valgrind 對(duì)內(nèi)存的分析

這里列出了多種的內(nèi)存泄露情況:

  • definitely lost: 肯定的內(nèi)存泄漏侦镇,這表示在程序退出時(shí)灵疮,有內(nèi)存沒有回收,但是也沒有指針指向該內(nèi)存壳繁。這種情況最為嚴(yán)重震捣。

  • indirectly lost: 間接的內(nèi)存泄漏荔棉,如類之中定義的指針指向的內(nèi)存沒有回收。這種情況和上述相同蒿赢。

  • possibly lost: 可能出現(xiàn)內(nèi)存泄漏江耀。這種情況需要仔細(xì)排查,可能代碼沒有問題诉植,也可能有異常的內(nèi)存泄露。

  • still reachable: 程序沒主動(dòng)釋放內(nèi)存昵观,在退出時(shí)候該內(nèi)存仍能訪問到晾腔。這種情況一般問題不大,因?yàn)槌绦蛲顺鲋蟛僮飨到y(tǒng)會(huì)回收程序的內(nèi)存啊犬,所以這種情況一般問題不大灼擂。

這里沒有給出具體泄露的內(nèi)容,需要加入?yún)?shù)--leak-check=full將完整的結(jié)果打印出來觉至,會(huì)指出對(duì)應(yīng)的引起內(nèi)存泄露的具體代碼剔应,可以繼續(xù)深入分析。

代碼調(diào)優(yōu)

這里進(jìn)行代碼調(diào)優(yōu)的時(shí)语御,需要利用qcachegrind來進(jìn)行分析峻贮。首先筆者先進(jìn)行安裝:

sudo apt-get install qcachegrind 

之后我們調(diào)用Valgrind來生成運(yùn)行數(shù)據(jù):

 valgrind --tool=callgrind -v main(需要分析的程序)

運(yùn)行之后在目錄下生成對(duì)應(yīng)的分析數(shù)據(jù),我們用qcachegrind 打開应闯,這里用的代碼是筆者之前實(shí)現(xiàn)的 SkipList纤控。

qcachegrind callgrind.out.29235 

接下來我們來分析對(duì)應(yīng)的結(jié)果:


valgrind 的分析結(jié)果

上圖顯示了各個(gè)函數(shù)的被調(diào)用的耗時(shí)百分比,我們可以選取對(duì)性能感興趣的函數(shù)來進(jìn)行深入分析碉纺。我們下面繼續(xù)分析其中一個(gè)函數(shù)被調(diào)用和它使用函數(shù)的性能情況

insert 的函數(shù)被外調(diào)用的情況

insert 函數(shù)調(diào)用函數(shù)的情況與耗時(shí)分析

所以通過上述數(shù)據(jù)船万,我們可以給出性能分析的證據(jù)和線索,依據(jù)這些信息來更好的優(yōu)化我們代碼的性能骨田。

3.小結(jié)

本文介紹了亡羊補(bǔ)牢的工具 GDB耿导,也簡(jiǎn)介了未雨綢繆的Valgrind 。通過上述工具對(duì)C++程序更加深入分析态贤。工欲善其事舱呻,必先利其器,希望大家也能好好掌握這些提供生產(chǎn)力的工具抵卫,讓 C++不再惱人狮荔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市介粘,隨后出現(xiàn)的幾起案子殖氏,更是在濱河造成了極大的恐慌,老刑警劉巖姻采,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雅采,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)婚瓜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門宝鼓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巴刻,你說我怎么就攤上這事愚铡。” “怎么了胡陪?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵沥寥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我柠座,道長(zhǎng)邑雅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任妈经,我火速辦了婚禮淮野,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吹泡。我一直安慰自己骤星,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布荞胡。 她就那樣靜靜地躺著妈踊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪泪漂。 梳的紋絲不亂的頭發(fā)上廊营,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音萝勤,去河邊找鬼露筒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敌卓,可吹牛的內(nèi)容都是我干的慎式。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼趟径,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼瘪吏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜗巧,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掌眠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后幕屹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蓝丙,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡级遭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渺尘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挫鸽。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鸥跟,靈堂內(nèi)的尸體忽然破棺而出丢郊,到底是詐尸還是另有隱情,我是刑警寧澤医咨,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布蚂夕,位于F島的核電站,受9級(jí)特大地震影響腋逆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侈贷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一惩歉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俏蛮,春花似錦撑蚌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至辣恋,卻和暖如春亮垫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背伟骨。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工饮潦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人携狭。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓继蜡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逛腿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子稀并,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 什么是coredump Coredump叫做核心轉(zhuǎn)儲(chǔ),它是進(jìn)程運(yùn)行時(shí)在突然崩潰的那一刻的一個(gè)內(nèi)存快照单默。操作系統(tǒng)在程...
    java菜閱讀 4,197評(píng)論 0 4
  • 今日份—-喪氣 2018年9月19日星期三碘举,昨天是九一...
    輒醉閱讀 155評(píng)論 0 0
  • 第二章 姐妹 兩次離別 1964年春,壓力機(jī)械廠分派了兩個(gè)前往濟(jì)南總部的學(xué)習(xí)機(jī)會(huì)雕凹,廠里的所有員工都躍躍欲試殴俱。 英子...
    老人魚閱讀 425評(píng)論 0 1