色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

內存泄漏如何避免

科技綠洲 ? 來源:Linux開發架構之路 ? 作者:Linux開發架構之路 ? 2023-11-10 11:04 ? 次閱讀

1. 內存溢出

內存溢出 OOM (out of memory),是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個int,但給它存了long才能存下的數,那就是內存溢出。

2. 內存泄漏

內存泄露 memory leak,是指程序在申請內存后,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積后果很嚴重,無論多少內存,遲早會被占光。最終的結果就是導致OOM。

內存泄漏是指你向系統申請分配內存進行使用(new),可是使用完了以后卻不歸還(delete),結果你申請到的那塊內存你自己也不能再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程序。

3. 造成內存泄露常見的三種情況

1,指針重新賦值

2,錯誤的內存釋放

3,返回值的不正確處理

3.1 指針重新賦值

如下代碼:

char * p = (char *)malloc(10);
char * np = (char *)malloc(10);

其中,指針變量 p 和 np 分別被分配了 10 個字節的內存。

如果程序需要執行如下賦值語句:

p=np;

這時候,指針變量 p 被 np 指針重新賦值,其結果是 p 以前所指向的內存位置變成了孤立的內存。它無法釋放,因為沒有指向該位置的引用,從而導致 10 字節的內存泄漏。

因此,在對指針賦值前,一定確保內存位置不會變為孤立的。

類似的情況,連續重復new的情況也是類似:

int *p = new int;
p = new int...;//錯誤

3.2 錯誤的內存釋放

假設有一個指針變量 p,它指向一個 10 字節的內存位置。該內存位置的第三個字節又指向某個動態分配的 10 字節的內存位置。

如果程序需要執行如下賦值語句時:

free(p);

很顯然,如果通過調用 free 來釋放指針 p,則 np 指針也會因此而變得無效。np 以前所指向的內存位置也無法釋放,因為已經沒有指向該位置的指針。換句話說,np 所指向的內存位置變為孤立的,從而導致內存泄漏。

因此,每當釋放結構化的元素,而該元素又包含指向動態分配的內存位置的指針時,應首先遍歷子內存位置(如本示例中的 np),并從那里開始釋放,然后再遍歷回父節點,如下面的代碼所示:

free(p->np);
free(p);

3.3 返回值的不正確處理

有時候,某些函數會返回對動態分配的內存的引用,如下面的示例代碼所示:

char *f(){
return (char *)malloc(10);
}
void f1(){
f();
}

函數 f1 中對 f 函數的調用并未處理該內存位置的返回地址,其結果將導致 f 函數所分配的 10 個字節的塊丟失,并導致內存泄漏。

4 在內存分配后忘記使用 free 進行釋放

4. 如何避免內存泄露?

  • 確保沒有在訪問空指針。
  • 每個內存分配函數都應該有一個 free 函數與之對應,alloca 函數除外。
  • 每次分配內存之后都應該及時進行初始化,可以結合 memset 函數進行初始化,calloc 函數除外。
  • 每當向指針寫入值時,都要確保對可用字節數和所寫入的字節數進行交叉核對。
  • 在對指針賦值前,一定要確保沒有內存位置會變為孤立的。
  • 每當釋放結構化的元素(而該元素又包含指向動態分配的內存位置的指針)時,都應先遍歷子內存位置并從那里開始釋放,然后再遍歷回父節點。
  • 始終正確處理返回動態分配的內存引用的函數返回值。

5.定位內存泄漏(valgrind)(重點)

5.1、基本概念

Valgrind是一個GPL的軟件,用于Linux(For x86, amd64 and ppc32)程序的內存調試和代碼剖析。你可以在它的環境中運行你的程序來監視內存的使用情況,比如C 語言中的malloc和free或者 C++中的new和 delete。使用Valgrind的工具包,你可以自動的檢測許多內存管理和線程的bug,避免花費太多的時間在bug尋找上,使得你的程序更加穩固。

安裝Valgrind

//valgrind下載
http://valgrind.org/downloads/valgrind-3.12.0.tar.bz2

valgrind安裝:
1. tar -jxvf valgrind-3.12.0.tar.bz2
2. cd valgrind-3.12.0
3. ./configure
4. make
5. sudo make install

應用環境:Linux

編程語言:C/C++

使用方法:編譯時加上-g選項,如 gcc -g filename.c -o filename,使用如下命令檢測內存使用情況:

最常用的命令格式:
valgrind --tool=memcheck --leak-check=full ./test

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes ./filename

其中--leak-check=full指的是完全檢查內存泄漏,--show-reachable=yes是顯示內存泄漏的地點,--trace-children=yes是跟入子進程。

如果您的程序是會正常退出的程序,那么當程序退出的時候valgrind自然會輸出內存泄漏的信息。如果您的程序是個守護進程,那么也不要緊,我們 只要在別的終端下殺死memcheck進程(因為valgrind默認使用memcheck工具,就是默認參數--tools=memcheck)

參數選擇

-tool= 最常用的選項。運行 valgrind中名為toolname的工具。默認memcheck。
memcheck ------> 這是valgrind應用最廣泛的工具,一個重量級的內存檢查器,能夠發現開發中絕大多數內存錯誤使用情況,比如:使用未初始化的內存,使用已經釋放了的內存,內存訪問越界等。
callgrind ------> 它主要用來檢查程序中函數調用過程中出現的問題。
cachegrind ------> 它主要用來檢查程序中緩存使用出現的問題。
helgrind ------> 它主要用來檢查多線程程序中出現的競爭問題。
massif ------> 它主要用來檢查程序中堆棧使用中出現的問題。
extension ------> 可以利用core提供的功能,自己編寫特定的內存調試工具
-h –help 顯示幫助信息。
-version 顯示valgrind內核的版本,每個工具都有各自的版本。
-q –quiet 安靜地運行,只打印錯誤信息。
-v –verbose 更詳細的信息, 增加錯誤數統計。
-trace-children=no|yes 跟蹤子線程? [default: no]
-track-fds=no|yes 跟蹤打開的文件描述?[default: no]
-time-stamp=no|yes 增加時間戳到LOG信息? [default: no]
-log-fd= 輸出LOG到描述符文件 [2=stderr]
-log-file= 將輸出的信息寫入到filename.PID的文件里,PID是運行程序的進行ID
-log-file-exactly= 輸出LOG信息到 file
-log-file-qualifier= 取得環境變量的值來做為輸出信息的文件名。[none]
-log-socket=ipaddr:port 輸出LOG到socket ,ipaddr:port

LOG信息輸出

-xml=yes 將信息以xml格式輸出,只有memcheck可用
-num-callers= show callers in stack traces [12]
-error-limit=no|yes 如果太多錯誤,則停止顯示新錯誤? [yes]
-error-exitcode= 如果發現錯誤則返回錯誤代碼 [0=disable]
-db-attach=no|yes 當出現錯誤,valgrind會自動啟動調試器gdb。[no]
-db-command= 啟動調試器的命令行選項[gdb -nw %f %p]

設計思路:根據軟件的內存操作維護一個有效地址空間表和無效地址空間表(進程的地址空間)

5.2、多個工具

1、Memcheck

最常用的工具,用來檢測程序中出現的內存問題,所有對內存的讀寫都會被檢測到,一切對malloc()/free()/new/delete的調用都會被捕獲。所以,Memcheck 工具主要檢查下面的程序錯誤

能夠檢測:

  • 使用未初始化的內存 (Use of uninitialised memory)
  • 使用已經釋放了的內存 (Reading/writing memory after it has been free’d)
  • 使用超過 malloc分配的內存空間(Reading/writing off the end of malloc’d blocks)
  • 對堆棧的非法訪問 (Reading/writing inappropriate areas on the stack)
  • 申請的空間是否有釋放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
  • malloc/free/new/delete申請和釋放內存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
  • src和dst的重疊(Overlapping src and dst pointers in memcpy() and related functions)
  • 重復free

圖片

Callgrind

和gprof類似的分析工具,但它對程序的運行觀察更是入微,能給我們提供更多的信息。和gprof不同,它不需要在編譯源代碼時附加特殊選項,但加上調試選項是推薦的。Callgrind收集程序運行時的一些數據,建立函數調用關系圖,還可以有選擇地進行cache模擬。在運行結束時,它會把分析數據寫入一個文件。callgrind_annotate可以把這個文件的內容轉化成可讀的形式。

Cachegrind

Cache分析器,它模擬CPU中的一級緩存I1,Dl和二級緩存,能夠精確地指出程序中cache的丟失和命中。如果需要,它還能夠為我們提供cache丟失次數,內存引用次數,以及每行代碼,每個函數,每個模塊,整個程序產生的指令數。這對優化程序有很大的幫助。

Helgrind

它主要用來檢查多線程程序中出現的競爭問題。Helgrind尋找內存中被多個線程訪問,而又沒有一貫加鎖的區域,這些區域往往是線程之間失去同步的地方,而且會導致難以發掘的錯誤。Helgrind實現了名為“Eraser”的競爭檢測算法,并做了進一步改進,減少了報告錯誤的次數。不過,Helgrind仍然處于實驗階段。

Massif

堆棧分析器,它能測量程序在堆棧中使用了多少內存,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少內存的使用,在帶有虛擬內存的現代系統中,它還能夠加速我們程序的運行,減少程序停留在交換區中的幾率。

5.3、使用原理

圖片

圖片

圖片

Memcheck 能夠檢測出內存問題,關鍵在于其建立了兩個全局表。

1、Valid-Value 表:

對于進程的整個地址空間中的每一個字節(byte),都有與之對應的 8 個 bits;對于 CPU 的每個寄存器,也有一個與之對應的 bit 向量。這些 bits 負責記錄該字節或者寄存器值是否具有有效的、已初始化的值。

2、Valid-Address 表

對于進程整個地址空間中的每一個字節(byte),還有與之對應的 1 個 bit,負責記錄該地址是否能夠被讀寫。

檢測原理:

  • 當要讀寫內存中某個字節時,首先檢查這個字節對應的 A bit。如果該A bit顯示該位置是無效位置,memcheck 則報告讀寫錯誤。
  • 內核(core)類似于一個虛擬的 CPU 環境,這樣當內存中的某個字節被加載到真實的 CPU 中時,該字節對應的 V bit也被加載到虛擬的 CPU 環境中。一旦寄存器中的值,被用來產生內存地址,或者該值能夠影響程序輸出,則 memcheck 會檢查對應的V bits,如果該值尚未初始化,則會報告使用未初始化內存錯誤。

5.4、具體使用

  1. 使用未初始化的內存(使用野指針)

這里我們定義了一個指針p,但并未給他開辟空間,即他是一個野指針,但我們卻使用它了

圖片

Valgrind檢測出我們程序使用了未初始化的變量,但并未檢測出內存泄漏。

圖片

2.在內存被釋放后進行讀/寫(使用野指針)

p所指向的內存被釋放了,p變成了野指針,但是我們卻繼續使用這片內存。

圖片

Valgrind檢測出我們使用了已經free掉的內存,并給出這片內存是哪里分配哪里釋放的。

圖片

3.從已分配內存塊的尾部進行讀/寫(動態內存越界)

我們動態地分配了一段數組,但我們在訪問個數組時發生了越界讀寫,程序crash掉。

圖片

Valgrind檢測出越界的位置。

圖片

注意:Valgrind不檢查靜態分配數組的使用情況!所以對靜態分配的數組,Valgrind表示無能為力!比如下面的例子,程序crash掉,我們卻不知道為什么。

圖片

圖片

4.內存泄漏

內存泄漏的原因在于沒有成對地使用malloc/free和new/delete,比如下面的例子。

圖片

Valgrind會給出程序中malloc和free的出現次數以判斷是否發生內存泄漏,比如對上面的程序運行memcheck,Valgrind的記錄顯示上面的程序用了1次malloc,卻調用了0次free,明顯發生了內存泄漏!

圖片

上面提示了我們可以使用–leak-check=full進一步獲取內存泄漏的信息,比如malloc和free的具體行號。

圖片

  1. 不匹配地使用malloc/new/new[] 和 free/delete/delete[]

正常使用new/delete和malloc/free是這樣子的:

圖片

圖片

而不匹配地使用malloc/new/new[] 和 free/delete/delete[]則會被提示mismacth:

圖片

圖片

6.兩次釋放內存

double free的情況同樣是根據malloc/free的匹配對數來體現的,比如free多了一次,Valgrind也會提示。

圖片

圖片

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3028

    瀏覽量

    74076
  • 程序
    +關注

    關注

    117

    文章

    3787

    瀏覽量

    81069
  • 函數
    +關注

    關注

    3

    文章

    4332

    瀏覽量

    62653
  • C 語言
    +關注

    關注

    0

    文章

    18

    瀏覽量

    14227
收藏 人收藏

    評論

    相關推薦

    Linux內存泄漏檢測實現原理與實現

    在使用沒有垃圾回收的語言時(如 C/C++),可能由于忘記釋放內存而導致內存被耗盡,這叫 內存泄漏。由于內核也需要自己管理內存,所以也可能出
    發表于 12-09 11:11 ?970次閱讀

    內存泄漏定位該如何去實現呢

    嵌入式之內存泄漏定位篇在嵌入式開發中,經常會使用malloc,free分配釋放堆內存,當malloc,free不配對使用時,就會導致內存一點點地泄露,直至堆
    發表于 12-17 07:24

    內存泄漏的特點和類型

    在計算機科學中,內存泄漏(memory leak)指由于疏忽或錯誤使程序未能釋放而造成不能再使用的內存的情況。內存泄漏并非指
    的頭像 發表于 06-20 10:58 ?2827次閱讀

    內存泄漏問題原理及檢視方法

    可能不少開發者都遇到過內存泄漏導致的網上問題,具體表現為單板在現網運行數月以后,因為內存耗盡而導致單板復位現象。一方面,內存泄漏問題屬于比較
    的頭像 發表于 10-10 10:42 ?2557次閱讀

    如何避免內存泄漏的方法和原則

    本文向讀者介紹了如何避免內存泄漏的方法和原則,在細節和大體方向上均給出一些可行性方案。讀者可以嘗試文中提出的方法,改進自己的代碼,大大減少內存泄漏
    的頭像 發表于 10-21 14:30 ?5916次閱讀
    如何<b class='flag-5'>避免</b><b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>的方法和原則

    如何使用ThreadLocal來避免內存泄漏

    本次給大家介紹重要的工具ThreadLocal。講解內容如下,同時介紹什么場景下發生內存泄漏,如何復現內存泄漏,如何正確使用它來避免
    的頭像 發表于 08-20 09:29 ?4243次閱讀
    如何使用ThreadLocal來<b class='flag-5'>避免</b><b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>

    什么是內存泄漏內存泄漏有哪些現象

    內存泄漏幾乎是很難避免的,不管是老手還是新手,都存在這個問題,甚至 Windows 與 Linux 這類系統軟件也或多或少存在著內存泄漏
    的頭像 發表于 09-05 17:24 ?9707次閱讀

    怎么解決C語言中的內存泄漏問題呢?

    只有在堆內存里面才會發生內存泄漏的問題,在棧內存中不會發生內存泄漏。因為棧
    發表于 06-11 17:31 ?578次閱讀
    怎么解決C語言中的<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>問題呢?

    什么是內存泄漏?如何避免JavaScript內存泄漏

    JavaScript 代碼中常見的內存泄漏的常見來源: 研究內存泄漏問題就相當于尋找符合垃圾回收機制的編程方式,有效避免對象引用的問題。
    發表于 10-27 11:30 ?400次閱讀
    什么是<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>?如何<b class='flag-5'>避免</b>JavaScript<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>

    內存泄漏會產生哪些后果

    內存泄漏原因 內存泄漏在C/C++這種不帶GC(Garbage Collection)的語言里,是一個經常發生的問題。因為沒有GC,所以分配的內存
    的頭像 發表于 11-10 15:06 ?794次閱讀
    <b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>會產生哪些后果

    線程內存泄漏問題的定位

    記錄一個關于線程內存泄漏問題的定位過程,以及過程中的收獲。 1. 初步定位 是否存在內存泄漏:想到內存
    的頭像 發表于 11-13 11:38 ?619次閱讀
    線程<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>問題的定位

    如何發現內存泄漏

    檢測兩個角度介紹在 Linux 環境進行內存泄漏檢測的方法,并重點介紹靜態分析工具 BEAM、動態監測工具 Valgrind 和 rational purify 的使用方法。相信通過本文的介紹,能給大家對處理其它產品或項目內存
    的頭像 發表于 11-13 15:41 ?605次閱讀

    內存溢出與內存泄漏:定義、區別與解決方案

    內存溢出與內存泄漏:定義、區別與解決方案? 內存溢出和內存泄漏是計算機科學中常見的問題,在開發和
    的頭像 發表于 12-19 14:10 ?2819次閱讀

    C語言內存泄漏問題原理

    內存泄漏問題只有在使用堆內存的時候才會出現,棧內存不存在內存泄漏問題,因為棧
    發表于 03-19 11:38 ?530次閱讀
    C語言<b class='flag-5'>內存</b><b class='flag-5'>泄漏</b>問題原理

    如何檢測內存泄漏

    檢測內存泄漏是軟件開發過程中一項至關重要的任務,它有助于識別和解決那些導致程序占用過多內存資源,從而影響程序性能甚至導致程序崩潰的問題。以下將詳細闡述幾種常見的內存
    的頭像 發表于 07-30 11:50 ?1931次閱讀
    主站蜘蛛池模板: 俄罗斯乌克兰战争原因| 99热久久这里只有精品视频| 穿白丝袜边走边尿白丝袜| 久久免费看视频| 在线免费观看成年人视频| 国产成人精品视频播放| 最近中文字幕完整版高清| OLDMAN老头456 TUBE| 看了n遍舍不得删的黄文| 男人把女人桶到高潮嗷嗷叫| 一个人看的HD免费高清视频| 黄色三级网站| 亚洲日韩中文字幕区| 久久re视频这里精品一本到99| 亚洲区 bt下载| 久久国产免费| 中文字幕在线观看国产| 快播电影频道| av色天堂2018在线观看| 欧美一区二区高清| 成人综合在线观看| 麻豆免费观看高清完整视频| 色欲AV亚洲午夜精品无码| 打开双腿狠狠蹂躏蜜桃臀| 日韩 亚洲 欧美 中文 高清| 大香伊蕉在人线国产最新| 天天爽夜夜爽| 国产在线观看免费观看| 亚洲综合AV在线在线播放| 久久精品在现线观看免费15| 97SE亚洲国产综合在线| 秋霞伦理高清视频在线| 国产精品A久久久久久久久| 人妻换人妻AA视频| 第一次破女视频出血视频| 消息称老熟妇乱视频一区二区| 挤奶门事件完整照片 | 一二三四在线观看高清电视剧| 久久久国产精品免费A片3D| 99国产精品久久| 天上人间影院久久国产|