linux內存泄露
① 嵌入式linux怎麼檢內存泄漏雨
1. 在需要內存泄漏檢查的代碼的開始調用void mtrace(void) (在mcheck.h中? 有聲明). mtrace為malloc等函數安裝hook, 用於記錄內存分配信息.在需要內存泄漏檢查的代碼的結束調用void muntrace(void).
注意: 一般情況下不要調用muntrace, 而讓程序自然結束. 因為可能有些釋放內存代碼要到muntrace之後才運行.
2. 用debug模式編譯被檢查代碼(-g或-ggdb)
3. 設置環境變數MALLOC_TRACE為一文件名, 這一文件將存有內存分配信息.
4. 運行被檢查程序, 直至結束或muntrace被調用.
5. 用mtrace命令解析內存分配Log文件($MALLOC_TRACE)
(mtrace foo $MALLOC_TRACE, where foo is the executible name)
如果有內存泄漏, mtrace會輸出分配泄漏
內存的代碼位置,以及分配數量.
附加說明
1. 可以將mtrace, muntrace放入信號處理函數(USR1, USR2), 以動態地進行內存泄漏檢查控制.
2. mtrace是個perl代碼, 如果你對符號地址與代碼文本的轉換感興趣, 可以讀一下.
3. again, 盡量不要用muntrace()
For C++ Leak:
檢查內存泄漏的方法除glibc提供外;還可以試試一些專用的程序。
很奇怪,redhat 9 居然不帶mtrace perl腳本,只好下載gcc源碼編譯了
wget --passive-ftp ftp://rpmfind.net/linux/redhat/9 ... -2.3.2-11.9.src.rpm
rpm -ivh glibc*.src.rpm
cd /usr/src/redhat/SPECS/
rpmbuild -ba glibc-9.spec
cd /var/tmp/glibc-2.3.2-root/usr/bin/
cp mtrace /usr/bin/
調試方法如下:
vi a.c
1 #include
2
3 int main()
4 {
5 mtrace();
6 malloc(10);
7 malloc(16);
8 return 0;
9 }
$gcc -g a.c #記得編譯帶-g調試選項
$export MALLOC_TRACE=a.log
$./a.out
$unset MALLOC_TRACE #記得執行完後unset變數,否則可能運行其他命令可能覆蓋log
$mtrace a.out a.log
Memory not freed:
-----------------
Address Size Caller
0x09b08378 0xa at /XXX/a.c:6
0x09b08388 0x10 at /XXX/a.c:7
可以看到,會顯示未釋放動態空間的代碼具體位置。
② linux內存泄漏怎麼查
可以使用對應的軟體測試工具來查,如parasoft的c/c++等
③ 怎麼樣來檢查Linux系統下內存泄漏
內存泄漏是指程序動態申請的內存在使用完後沒有釋放,導致這段內存不能被操作系統回收再利用。 例如這段程序,申請了4個位元組的空間但沒有釋放,有4個位元組的內存泄漏。
#include <iostream>using namespace std;int main()
{ int *p = new int(1); cout <<*p<<endl; return 0}
1
2
3
4
5
6
7
8
9
隨著時間的推移,泄漏的內存越來越多,可用的內存越來越少,輕則性能受損,重則系統崩潰。
一般情況下,發生內存泄漏時,重啟就可以回收泄漏的內存。但是對於Linux,通常跑的是伺服器程序,不可以隨意重啟,在內存泄漏問題上就要格外小心。
內存泄漏特點
難復現 — 要運行到足夠長的時間才會暴露。
難定位 — 出錯位置是隨機的,看不出與內存泄漏的代碼有什麼聯系。
最簡單的方法
為了避免寫出內存泄漏的程序,通常會有這樣的編程規范,要求我們在寫程序時申請和釋放成對出現的。因為每一次申請都意味著必須有一次釋放與它相對應。
基於這個特點,一種簡單的方法就是在代碼中統計申請和釋放的次數,如果申請和釋放的數量不同,就認為是內存泄漏了。
#include "stdio.h"#include "stdlib.h"int malloc_count, free_count;void * my_malloc(int size)
{
malloc_count++; return malloc(size);
}void my_free(void *p)
{
free_count++; free(p);
}int main()
{
count = 0; int *p1 = (int *)my_malloc(sizeif(int)) int *p2 = (int *)my_malloc(sizeif(int)) printf("%d, %d", p1, p2);
my_free(p1); if(malloc_count != free_count) printf("memory leak!\n"); return 0}
④ 如何定位分析linux內存泄漏問題
1、閱讀源代碼及分析動態內存的使用
由於之前沒有做過類似的問題(純屬小白了,慘遭鄙視....),所以就想著通過自己去看代碼,查找裡面涉及到使用動態內存的代碼段去定位問題(現在想想,真是太幼稚了,大家見笑了...),但是自己還是去通過對源代碼跟蹤、分析,主要是對動態分配的內存(如malloc函數分配的內存)、一些文件描述符等進行跟蹤,分析在程序邏輯中對動態分配的內存有沒有手動進行釋放,打開的文件描述符有沒有關閉等這些代碼一點點的去分析,當然這也是熟悉代碼,了解的一個過程。
2、利用memwatch內存檢測工具對程序進行內存分析
Memwatch是一款C語言的內存檢測工具。memwatch使用它自己定義的功能函數取代所有在你的程序中用ANSI C定義的內存分配函數,memwatch的內存分配函數包含了所有的分配記錄信息。memwatch功能默認不是開啟的,除非定義了MEMWATCH,否則在代碼中不會跟蹤相關的內存使用情況。memwatch通常將它的數據寫入到memwatch.log文件中,它也可以被重定向.更多Linux操作知識,可以網路《Linux就該這么學》。
⑤ 如何在linux操作系統下檢測內存泄漏
內存泄漏是指程序動態申請的內存在使用完後沒有釋放,導致這段內存不能被操作系統回收再利用。
例如這段程序,申請了4個位元組的空間但沒有釋放,有4個位元組的內存泄漏。
{ int *p = new int(1); cout <<*p<<endl; return 0}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
隨著時間的推移,泄漏的內存越來越多,可用的內存越來越少,輕則性能受損,重則系統崩潰。
一般情況下,發生內存泄漏時,重啟就可以回收泄漏的內存。但是對於Linux,通常跑的是伺服器程序,不可以隨意重啟,在內存泄漏問題上就要格外小心。
內存泄漏特點難復現 — 要運行到足夠長的時間才會暴露。
難定位 — 出錯位置是隨機的,看不出與內存泄漏的代碼有什麼聯系。
為了避免寫出內存泄漏的程序,通常會有這樣的編程規范,要求我們在寫程序時申請和釋放成對出現的。因為每一次申請都意味著必須有一次釋放與它相對應。
基於這個特點,一種簡單的方法就是在代碼中統計申請和釋放的次數,如果申請和釋放的數量不同,就認為是內存泄漏了。
#include "stdio.h"#include "stdlib.h"int malloc_count, free_count;void * my_malloc(int size){
malloc_count++; return malloc(size);
}void my_free(void *p)
{
free_count++; free(p);
}int main()
{
count = 0; int *p1 = (int *)my_malloc(sizeif(int)) int *p2 = (int *)my_malloc(sizeif(int)) printf("%d, %d", p1, p2);
my_free(p1); if(malloc_count != free_count) printf("memory leak! "); return 0}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 優點:
直觀,容易理解,容易實現
- 缺點:
1.該方法要求運行結束時對運行中產生的列印分析才能知道結果。
2.該方法要求封裝所有申請和釋放空間的函數,並在調用的地方修改成調用封裝後的函數。雖然C中申請/釋放內存介面並不多,但是對於一個大型的項目,調用這些介面的地方卻是很多的,要全部替換是一個比較大的工作量。
3.只對C語言適用,不能應用於C++
4.對於所調用的庫不適用。如果希望應用於庫,則要修改庫代碼
5.只能檢測是否泄漏,卻沒有具體信息,比如泄漏了多少空間
6.不能說明是哪一行代碼引起了泄漏
改進這種方法雖然簡單的,卻有許多的不足,無法真正應用於項目中。欲知怎樣改進,且看下回分解。
⑥ linux內存泄漏如何定位
1、閱讀源代碼及分析動態內存的使用 由於之前沒有做過類似的問題(純屬小白了,慘遭鄙視.),所以就想著通過自己去看代碼,查找...
2、利用memwatch內存檢測工具對程序進行內存分析Memwatch是一款C語言的內存檢測工具。memwatch使用它自己定義的功能函數取代所有在你的程...
⑦ linux中檢查內存泄漏的工具有哪些
Valgrind 是一款 Linux下(支持 x86、x86_64和ppc32)程序的內存調試工具,它可以對編譯後的二進製程序進行內存使用監測(C語言中的malloc和free,以及C++中的new和delete),找出內存泄漏問題。
⑧ 如何在Linux操作系統下檢測內存泄漏
Linux操作系統應用專區1.開發背景:
在 Windows 下使用 VC 編程時,我們通常需要 DEBUG 模式下運行程序,而後調試器將在退出程序時,列印出程序運行過程中在堆上分配而沒有釋放的內存信息,其中包括代碼文件名、行號以及內存大小。該功能是 MFC Framework 提供的內置機制,封裝在其類結構體系內部。
在 Linux 或者 Unix 下,我們的 C++ 程序缺乏相應的手段來檢測內存信息,而只能使用 top 指令觀察進程的動態內存總額。而且程序退出時,我們無法獲知任何內存泄漏信息。為了更好的輔助在 linux 下程序開發,我們在我們的類庫項目中設計並實現了一個內存檢測子系統。下文將簡述 C++ 中的 new 和 delete 的基本原理,並講述了內存檢測子系統的實現原理、實現中的技巧,並對內存泄漏檢測的高級話題進行了討論。2.New和delete的原理
當我們在程序中寫下 new 和 delete 時,我們實際上調用的是 C++ 語言內置的 new operator 和 delete operator。所謂語言內置就是說我們不能更改其含義,它的功能總是一致的。以 new operator 為例,它總是先分配足夠的內存,而後再調用相應的類型的構造函數初始化該內存。而 delete operator 總是先調用該類型的析構函數,而後釋放內存(圖1)。我們能夠施加影響力的事實上就是 new operator 和 delete operator 執行過程中分配和釋放內存的方法。
new operator 為分配內存所調用的函數名字是 operator new,其通常的形式是 void * operator new(size_t size); 其返回值類型是 void*,因為這個函數返回一個未經處理(raw)的指針,未初始化的內存。參數 size 確定分配多少內存,你能增加額外的參數重載函數 operator new,但是第一個參數類型必須是 size_t。
delete operator 為釋放內存所調用的函數名字是 operator delete,其通常的形式是 void operator delete(void *memoryToBeDeallocated);它釋放傳入的參數所指向的一片內存區。
這里有一個問題,就是當我們調用 new operator 分配內存時,有一個 size 參數表明需要分配多大的內存。但是當調用 delete operator 時,卻沒有類似的參數,那麼 delete operator 如何能夠知道需要釋放該指針指向的內存塊的大小呢?答案是:對於系統自有的數據類型,語言本身就能區分內存塊的大小,而對於自定義數據類型(如我們自定義的類),則 operator new 和 operator delete 之間需要互相傳遞信息。
當我們使用 operator new 為一個自定義類型對象分配內存時,實際上我們得到的內存要比實際對象的內存大一些,這些內存除了要存儲對象數據外,還需要記錄這片內存的大小,此方法稱為 cookie。這一點上的實現依據不同的編譯器不同。(例如 MFC 選擇在所分配內存的頭部存儲對象實際數據,而後面的部分存儲邊界標志和內存大小信息。g++ 則採用在所分配內存的頭 4 個自己存儲相關信息,而後面的內存存儲對象實際數據。)當我們使用 delete operator 進行內存釋放操作時,delete operator 就可以根據這些信息正確的釋放指針所指向的內存塊。
以上論述的是對於單個對象的內存分配/釋放,當我們為數組分配/釋放內存時,雖然我們仍然使用 new operator 和 delete operator,但是其內部行為卻有不同:new operator 調用了operator new 的數組版的兄弟- operator new[],而後針對每一個數組成員調用構造函數。而 delete operator 先對每一個數組成員調用析構函數,而後調用 operator delete[] 來釋放內存。需要注意的是,當我們創建或釋放由自定義數據類型所構成的數組時,編譯器為了能夠標識出在 operator delete[] 中所需釋放的內存塊的大小,也使用了編譯器相關的 cookie 技術。
⑨ 如何在linux下檢測內存泄漏
linux操作系統應用專區
1.開發背景:
在
windows
下使用
vc
編程時,我們通常需要
debug
模式下運行程序,而後調試器將在退出程序時,列印出程序運行過程中在堆上分配而沒有釋放的內存信息,其中包括代碼文件名、行號以及內存大小。該功能是
mfc
framework
提供的內置機制,封裝在其類結構體系內部。
在
linux
或者
unix
下,我們的
c++
程序缺乏相應的手段來檢測內存信息,而只能使用
top
指令觀察進程的動態內存總額。而且程序退出時,我們無法獲知任何內存泄漏信息。為了更好的輔助在
linux
下程序開發,我們在我們的類庫項目中設計並實現了一個內存檢測子系統。下文將簡述
c++
中的
new
和
delete
的基本原理,並講述了內存檢測子系統的實現原理、實現中的技巧,並對內存泄漏檢測的高級話題進行了討論。
2.new和delete的原理
當我們在程序中寫下
new
和
delete
時,我們實際上調用的是
c++
語言內置的
new
operator
和
delete
operator。所謂語言內置就是說我們不能更改其含義,它的功能總是一致的。以
new
operator
為例,它總是先分配足夠的內存,而後再調用相應的類型的構造函數初始化該內存。而
delete
operator
總是先調用該類型的析構函數,而後釋放內存(圖1)。我們能夠施加影響力的事實上就是
new
operator
和
delete
operator
執行過程中分配和釋放內存的方法。
new
operator
為分配內存所調用的函數名字是
operator
new,其通常的形式是
void
*
operator
new(size_t
size);
其返回值類型是
void*,因為這個函數返回一個未經處理(raw)的指針,未初始化的內存。參數
size
確定分配多少內存,你能增加額外的參數重載函數
operator
new,但是第一個參數類型必須是
size_t。
delete
operator
為釋放內存所調用的函數名字是
operator
delete,其通常的形式是
void
operator
delete(void
*memorytobedeallocated);它釋放傳入的參數所指向的一片內存區。
這里有一個問題,就是當我們調用
new
operator
分配內存時,有一個
size
參數表明需要分配多大的內存。但是當調用
delete
operator
時,卻沒有類似的參數,那麼
delete
operator
如何能夠知道需要釋放該指針指向的內存塊的大小呢?答案是:對於系統自有的數據類型,語言本身就能區分內存塊的大小,而對於自定義數據類型(如我們自定義的類),則
operator
new
和
operator
delete
之間需要互相傳遞信息。
當我們使用
operator
new
為一個自定義類型對象分配內存時,實際上我們得到的內存要比實際對象的內存大一些,這些內存除了要存儲對象數據外,還需要記錄這片內存的大小,此方法稱為
cookie。這一點上的實現依據不同的編譯器不同。(例如
mfc
選擇在所分配內存的頭部存儲對象實際數據,而後面的部分存儲邊界標志和內存大小信息。g++
則採用在所分配內存的頭
4
個自己存儲相關信息,而後面的內存存儲對象實際數據。)當我們使用
delete
operator
進行內存釋放操作時,delete
operator
就可以根據這些信息正確的釋放指針所指向的內存塊。
以上論述的是對於單個對象的內存分配/釋放,當我們為數組分配/釋放內存時,雖然我們仍然使用
new
operator
和
delete
operator,但是其內部行為卻有不同:new
operator
調用了operator
new
的數組版的兄弟-
operator
new[],而後針對每一個數組成員調用構造函數。而
delete
operator
先對每一個數組成員調用析構函數,而後調用
operator
delete[]
來釋放內存。需要注意的是,當我們創建或釋放由自定義數據類型所構成的數組時,編譯器為了能夠標識出在
operator
delete[]
中所需釋放的內存塊的大小,也使用了編譯器相關的
cookie
技術。
⑩ linux c 內存泄漏問題
具體來說,myfree中的num變數在內存中緊鄰著p變數,如果你將num申明為int,那他只佔四個位元組,而你初始化num的時候 memcpy(&num, p, sizeof(size_t)); 卻會將8個位元組拷進去,這會修改緊鄰這num的變數p,直接導致p被清零(如果malloc free外加修改的話,清的不一定是0),而free函數在傳入空指針是不做處理的。我把代碼修改了一下,你可以看一下下面程序的輸出,對應myfree的free那一行,實際被free的是空指針。
#include<stdio.h>
#include<malloc.h>
#include<pthread.h>
#include<unistd.h>
intfCnt=0,mCnt=0;
pthread_mutex_tmutex;
void*mynew(size_tsz){
void*p=malloc(sizeof(size_t)+sz);
memcpy(p,&sz,sizeof(size_t));
pthread_mutex_lock(&mutex);
mCnt+=sz+sizeof(size_t);
printf("mallocsz[%d],mCnt[%d],fCnt[%d] ",sz+sizeof(size_t),mCnt,
fCnt);
pthread_mutex_unlock(&mutex);
returnp+sizeof(size_t);
}
voidmyfree(void*prt){
void*p=prt-sizeof(size_t);
if(p==NULL){
printf("pbufisNULL ");
return;
}
intnum=0;//error!
//size_tnum=0;
printf("%p,%p ",&p,&num);
memcpy(&num,p,sizeof(size_t));
pthread_mutex_lock(&mutex);
fCnt+=num+sizeof(size_t);
printf("freesz[%d],fCnt[%d],mCnt[%d] ",num,fCnt,mCnt);
pthread_mutex_unlock(&mutex);
printf("trytofree%p ",p);
free(p);
}
intmain(){
void*p=mynew(100);
printf("pis%p ",p);
myfree(p);
usleep(1000000);
return0;
}