RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

valgrind檢測內(nèi)存問題的原理

嵌入式應(yīng)用研究院 ? 來源:嵌入式應(yīng)用研究院 ? 2023-05-23 09:30 ? 次閱讀

1、valgrind檢測原理

valgrind 是一個(gè)提供了一些 debug 和優(yōu)化的工具的工具箱,可以使得你的程序減少內(nèi)存泄漏或者錯(cuò)誤訪問。valgrind 默認(rèn)使用 memcheck 去檢查內(nèi)存問題。memcheck 檢測內(nèi)存問題的原理如下圖所示:

469125e8-f8f5-11ed-90ce-dac502259ad0.png

Memcheck 能夠檢測出內(nèi)存問題,關(guān)鍵在于其建立了兩個(gè)全局表。

valid-value map:對于進(jìn)程的整個(gè)地址空間中的每一個(gè)字節(jié)(byte),都有與之對應(yīng)的 8 個(gè) bits;對于 CPU 的每個(gè)寄存器,也有一個(gè)與之對應(yīng)的 bit 向量。這些 bits 負(fù)責(zé)記錄該字節(jié)或者寄存器值是否具有有效的、已初始化的值。

valid-address map:對于進(jìn)程整個(gè)地址空間中的每一個(gè)字節(jié)(byte),還有與之對應(yīng)的 1 個(gè) bit,負(fù)責(zé)記錄該地址是否能夠被讀寫。在兩個(gè)全局表的基礎(chǔ)上,以如下方式進(jìn)行檢測:

當(dāng)要讀寫內(nèi)存中某個(gè)字節(jié)時(shí),首先檢查 valid-address map 中這個(gè)字節(jié)對應(yīng)的 A bit。

如果該A bit顯示該位置是無效位置,memcheck 則報(bào)告讀寫錯(cuò)誤。內(nèi)核(core)類似于一個(gè)虛擬的 CPU 環(huán)境,這樣當(dāng)內(nèi)存中的某個(gè)字節(jié)被加載到真實(shí)的 CPU 中時(shí),該字節(jié)對應(yīng)的 V bit (在 valid-value map 中) 也被加載到虛擬的 CPU 環(huán)境中。一旦寄存器中的值,被用來產(chǎn)生內(nèi)存地址,或者該值能夠影響程序輸出,則 memcheck 會檢查對應(yīng)的 V bits,如果該值尚未初始化,則會報(bào)告使用未初始化內(nèi)存錯(cuò)誤。

不過valgrind也不是萬能的,對于棧上的內(nèi)存空間操作就無法檢測到。

2、命令選項(xiàng)

基本命令:valgrind --leak-check=yes ./a.out arg1 arg2

為了能夠定位到源代碼的行,建議編譯時(shí)加上-g選項(xiàng),并選擇O0優(yōu)化

3、使用示例

示例代碼:

#include
intmain()
{
int*x=(int*)malloc(10*sizeof(int));
x[10]=1;//問題1,越界了
return0;//問題2,沒有釋放內(nèi)存
}

執(zhí)行valgrind檢測后的結(jié)果:

barret@Barret-PC:~$valgrind--leak-check=yes./a.out
==393==Memcheck,amemoryerrordetector
==393==Copyright(C)2002-2017,andGNUGPL'd,byJulianSewardetal.
==393==UsingValgrind-3.15.0andLibVEX;rerunwith-hforcopyrightinfo
==393==Command:./a.out
==393==
==393==Invalidwriteofsize4
==393==at0x10916B:main(a.cpp:6)
==393==Address0x4a47068is0bytesafterablockofsize40alloc'd
==393==at0x483B7F3:malloc(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393==by0x10915E:main(a.cpp:5)
==393==
==393==
==393==HEAPSUMMARY:
==393==inuseatexit:40bytesin1blocks
==393==totalheapusage:1allocs,0frees,40bytesallocated
==393==
==393==40bytesin1blocksaredefinitelylostinlossrecord1of1
==393==at0x483B7F3:malloc(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393==by0x10915E:main(a.cpp:5)
==393==
==393==LEAKSUMMARY:
==393==definitelylost:40bytesin1blocks
==393==indirectlylost:0bytesin0blocks
==393==possiblylost:0bytesin0blocks
==393==stillreachable:0bytesin0blocks
==393==suppressed:0bytesin0blocks
==393==
==393==Forlistsofdetectedandsuppressederrors,rerunwith:-s
==393==ERRORSUMMARY:2errorsfrom2contexts(suppressed:0from0)

結(jié)果解析如下:

==393==:執(zhí)行程序的進(jìn)程ID

Invalid write of size 4:表示發(fā)現(xiàn)一個(gè)錯(cuò)誤,這里顯示源代碼第6行有錯(cuò)誤,這里很明顯是越界了,所以顯示invalid write錯(cuò)誤

40 bytes in 1 blocks are definitely lost in loss record 1 of 1:內(nèi)存泄露錯(cuò)誤,泄漏的大小是10* sizeof(int)40byte。

LEAK summary也會顯示內(nèi)存泄漏的情況

4、分析常見內(nèi)存問題

4.1、寫入非法內(nèi)存地址

上面的例子已經(jīng)展示了這種情況,訪問分配的內(nèi)存區(qū)域之外的空間,valgrind會上報(bào)如下的錯(cuò)誤:

Invalid

write of size x

后跟調(diào)用棧信息

4.2、讀取非法內(nèi)存地址

和上一個(gè)情況類似,不同 的是讀取而不是寫入,錯(cuò)誤信息如下:

Invalid

read of size x

后跟調(diào)用棧信息

4.3、讀取未初始化內(nèi)存區(qū)域

#include

intmain()
{
int*x=(int*)malloc(10*sizeof(int));
inta=x[1]+1;//不初始化就使用內(nèi)存的值
free(x);
returna;
}

valgrind顯示如下錯(cuò)誤:

==427==Syscallparamexit_group(status)**containsuninitialisedbyte(s)**
==427==at0x4938136:Exit(exit.c:31)
==427==by0x489BB41:__run_exit_handlers(exit.c:132)
==427==by0x489BBDF:exit(exit.c:139)
==427==by0x48790B9:(belowmain)(libc-start.c:342)

4.4、內(nèi)存雙重釋放

示例:

#include

intmain()
{
int*x=(int*)malloc(10*sizeof(int));
free(x);//free兩次
free(x);
return0;
}

valgrind顯示如下錯(cuò)誤,顯示兩次free的位置:

==436==Invalidfree()/delete/delete[]/realloc()
==436==**at0x483CA3F:free(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==436==by0x10919A:main(a.cpp:7)
==436==Address0x4a47040is0bytesinsideablockofsize40free'd
==436==at0x483CA3F:free(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==436==by0x10918E:main(a.cpp:6)**
==436==Blockwasalloc'dat
==436==at0x483B7F3:malloc(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==436==by0x10917E:main(a.cpp:5)
審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3019

    瀏覽量

    74003
  • 程序
    +關(guān)注

    關(guān)注

    117

    文章

    3785

    瀏覽量

    81003
  • Valgrind
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

    6807

原文標(biāo)題:Linux內(nèi)存泄漏調(diào)試?yán)?valgrind

文章出處:【微信號:嵌入式應(yīng)用研究院,微信公眾號:嵌入式應(yīng)用研究院】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    檢測內(nèi)存泄漏和內(nèi)存違例,Valgrind不可少!

    Valgrind可以檢測內(nèi)存泄漏和內(nèi)存違例,但是用Valgrind生成的日志信息結(jié)合kcachegrind就可以查看C程序的執(zhí)行線路圖,調(diào)用
    的頭像 發(fā)表于 05-07 08:45 ?6463次閱讀
    <b class='flag-5'>檢測</b><b class='flag-5'>內(nèi)存</b>泄漏和<b class='flag-5'>內(nèi)存</b>違例,<b class='flag-5'>Valgrind</b>不可少!

    使用valgrind對代碼進(jìn)行內(nèi)存泄露檢測

    代碼可能存在內(nèi)存泄露怎么辦?
    發(fā)表于 08-21 15:30 ?392次閱讀
    使用<b class='flag-5'>valgrind</b>對代碼進(jìn)行<b class='flag-5'>內(nèi)存</b>泄露<b class='flag-5'>檢測</b>

    嵌入式相關(guān)的動態(tài)檢測工具Valgrind簡介

    Valgrind是一套Linux下,開放源代碼(GPL V2)的仿真調(diào)試工具的集合。
    的頭像 發(fā)表于 11-08 09:41 ?1992次閱讀
    嵌入式相關(guān)的動態(tài)<b class='flag-5'>檢測</b>工具<b class='flag-5'>Valgrind</b>簡介

    一種利用調(diào)試軟件Valgrind進(jìn)行嵌入式應(yīng)用程序錯(cuò)誤查找的技術(shù)

    本文介紹了一種利用調(diào)試軟件Valgrind進(jìn)行嵌入式應(yīng)用程序錯(cuò)誤查找的技術(shù),利用它可以高效、自動地查找出程序中的多種錯(cuò)誤。首先介紹了嵌入式程序常見錯(cuò)誤,接著研究了Valgrind的工作原理,介紹了利用Valgrind進(jìn)行程序錯(cuò)誤
    發(fā)表于 04-23 06:49

    valgrind是怎樣去移植源碼的

    嵌入式內(nèi)存檢測工具-valgrind移植源碼較快)準(zhǔn)備:解壓tar -jxvf valgrind-3.16.1.tar.bz2進(jìn)入valgrind
    發(fā)表于 12-17 07:56

    寫了一個(gè)內(nèi)存泄漏檢查工具

    嵌入式環(huán)境內(nèi)存泄漏檢查比較麻煩,valgrind比較適合于在pc上跑,嵌入式上首先移植就很麻煩,移植完了內(nèi)存比較小,跑起來也比較費(fèi)勁。所以手動寫了一個(gè)內(nèi)存泄漏檢查工具,基本思路是,ho
    發(fā)表于 12-17 08:25

    如何編譯使用內(nèi)存泄漏的定位工具

    1.我們知道有個(gè)內(nèi)存泄漏的定位工具: valgrind, 非常優(yōu)秀?,F(xiàn)在已經(jīng)支持arm版本,下面看看如何編譯使用:2.下載源碼:
    發(fā)表于 12-17 08:13

    Linux C/C++內(nèi)存泄漏檢測工具:Valgrind

    Valgrind 是一款 Linux下(支持 x86、x86_64和ppc32)程序的內(nèi)存調(diào)試工具,它可以對編譯后的二進(jìn)制程序進(jìn)行內(nèi)存使用監(jiān)測(C語言中的malloc和free,以及
    發(fā)表于 04-02 14:33 ?615次閱讀

    電腦的內(nèi)存頻率該如何檢測

    ,選購電腦內(nèi)存條的時(shí)候,需要檢測電腦的內(nèi)存頻率,那么一個(gè)電腦的內(nèi)存頻率到底該如何檢測呢,下面跟小編去學(xué)習(xí)幾招輕松解決
    發(fā)表于 06-14 10:55 ?2108次閱讀

    內(nèi)存泄漏的檢測方法

    的。其實(shí)不然,防止內(nèi)存泄露要從良好的編程習(xí)慣做起,另外重要的一點(diǎn)就是要加強(qiáng)單元測試(Unit Test),而valgrind就是這樣一款優(yōu)秀的工具。
    的頭像 發(fā)表于 06-20 11:01 ?3145次閱讀

    使用valgrind的callgrind工具進(jìn)行多線程性能分析

    valgrind是開源的性能分析利器。 根據(jù)它的文檔,可以用它來檢查內(nèi)存泄漏等問題,還可以用來生成函數(shù)的調(diào)用圖,就這兩個(gè)功能就足夠有吸引力了。
    的頭像 發(fā)表于 06-22 09:51 ?2958次閱讀

    valgrind基本功能介紹、基礎(chǔ)使用方法說明

    Valgrind是一套Linux下,開放源代碼(GPL V2)的仿真調(diào)試工具的集合。
    的頭像 發(fā)表于 11-14 12:40 ?2487次閱讀

    如何使用valgrind對代碼進(jìn)行內(nèi)存泄露檢測

    代碼可能存在 內(nèi)存泄露 怎么辦? 使用 valgrind 可以對代碼進(jìn)行內(nèi)存泄露檢測。 valgrind下載安裝 安裝: 1 、tar –j
    的頭像 發(fā)表于 10-04 14:56 ?850次閱讀
    如何使用<b class='flag-5'>valgrind</b>對代碼進(jìn)行<b class='flag-5'>內(nèi)存</b>泄露<b class='flag-5'>檢測</b>

    如何發(fā)現(xiàn)內(nèi)存泄漏

    檢測兩個(gè)角度介紹在 Linux 環(huán)境進(jìn)行內(nèi)存泄漏檢測的方法,并重點(diǎn)介紹靜態(tài)分析工具 BEAM、動態(tài)監(jiān)測工具 Valgrind 和 rational purify 的使用方法。相信通過本
    的頭像 發(fā)表于 11-13 15:41 ?591次閱讀

    如何檢測內(nèi)存泄漏

    檢測內(nèi)存泄漏是軟件開發(fā)過程中一項(xiàng)至關(guān)重要的任務(wù),它有助于識別和解決那些導(dǎo)致程序占用過多內(nèi)存資源,從而影響程序性能甚至導(dǎo)致程序崩潰的問題。以下將詳細(xì)闡述幾種常見的內(nèi)存泄漏
    的頭像 發(fā)表于 07-30 11:50 ?1796次閱讀
    RM新时代网站-首页