熱搜:win11繞過(guò)硬件限制安裝 一鍵重裝Win10系統(tǒng) 最干凈的u盤(pán)啟動(dòng)盤(pán) 真正純凈版的win7系統(tǒng)
時(shí)間:2015-08-11 11:30:25 作者:zhijie 來(lái)源:系統(tǒng)之家 1. 掃描二維碼隨時(shí)看資訊 2. 請(qǐng)使用手機(jī)瀏覽器訪問(wèn): https://m.xitongzhijia.net/xtjc/20150811/55157.html 手機(jī)查看 評(píng)論 反饋
在使用Linux系統(tǒng)編寫(xiě)代碼過(guò)程中,有可能會(huì)發(fā)送內(nèi)存泄露的問(wèn)題。所以用戶(hù)就應(yīng)該要學(xué)會(huì)檢查內(nèi)存,那么Linux如何檢查內(nèi)存呢?一般都是使用一些工具,本文就來(lái)介紹一下Linux系統(tǒng)中怎么使用valgrind檢查內(nèi)存。
請(qǐng)看一下代碼:
#include 《stdlib.h》
#include 《stdio.h》
#include 《string.h》
static void mem_leak1(void)
{
char *p = malloc(1);
}
static void mem_leak2(void)
{
FILE *fp = fopen(“test.txt”, “w”);
}
static void mem_overrun1(void)
{
char *p = malloc(1);
*(short*)p = 2;
free(p);
}
static void mem_overrun2(void)
{
char array[5];
strcpy(array, “hello”);
}
static void mem_double_free(void)
{
char *p = malloc(1);
free(p);
free(p);
}
static void mem_use_wild_pointer(void)
{
char *p = (void*)0x80184800;
*p = 1;
}
static void mem_free_wild_pointer(void)
{
char *p;
free(p);
}
int main()
{
mem_leak1();
mem_leak2();
mem_overrun1();
mem_overrun2();
mem_double_free();
//mem_use_wild_pointer();
mem_free_wild_pointer();
return 0;
}
常見(jiàn)的內(nèi)存問(wèn)題:
1. 動(dòng)態(tài)內(nèi)存泄露;
2. 資源泄露,這里以文件描述符為例;
3. 動(dòng)態(tài)內(nèi)存越界;
4.數(shù)組內(nèi)存越界;
5.動(dòng)態(tài)內(nèi)存double free;
6.使用野指針,即未初始化的指針;
7.釋放野指針,即未初始化的指針;
其中由于本示例代碼過(guò)于簡(jiǎn)單,第6中情況,使用野指針會(huì)直接導(dǎo)致crash,所以在main中,并沒(méi)有真正的調(diào)用那個(gè)示例代碼。由于 valgrind只能檢測(cè)執(zhí)行到的代碼,所以在后面的報(bào)告中,不會(huì)報(bào)告第6種錯(cuò)誤情況。但是,在大型的項(xiàng)目中,有可能使用野指針并不會(huì)導(dǎo)致程序 crash。另外上面的7中情況,有些情況嚴(yán)格的說(shuō),實(shí)際上可以歸為一類(lèi)。
執(zhí)行valgrind來(lái)檢測(cè)內(nèi)存錯(cuò)誤:
valgrind --track-fds=yes --leak-check=full --undef-value-errors=yes 。/a.out
上面那些option的具體含義,可以參加valgrind --help,其中有些option默認(rèn)就是打開(kāi)的,不過(guò)我習(xí)慣于明確的使用option,以示清晰。
執(zhí)行后的報(bào)告:
==2326== Memcheck, a memory error detector
==2326== Copyright (C) 2002-2009, and GNU GPL‘d, by Julian Seward et al.
==2326== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==2326== Command: 。/a.out
==2326==
/* 這里檢測(cè)到了動(dòng)態(tài)內(nèi)存的越界,提示Invalid write。*/
==2326== Invalid write of size 2
==2326== at 0x80484B4: mem_overrun1 (in /home/fgao/works/test/a.out)
==2326== by 0x8048553: main (in /home/fgao/works/test/a.out)
==2326== Address 0x40211f0 is 0 bytes inside a block of size 1 alloc’d
==2326== at 0x4005BDC: malloc (vg_replace_malloc.c:195)
==2326== by 0x80484AD: mem_overrun1 (in /home/fgao/works/test/a.out)
==2326== by 0x8048553: main (in /home/fgao/works/test/a.out)
==2326==
/* 這里檢測(cè)到了double free問(wèn)題,提示Invalid Free */
==2326== Invalid free() / delete / delete[]
==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
==2326== by 0x8048514: mem_double_free (in /home/fgao/works/test/a.out)
==2326== by 0x804855D: main (in /home/fgao/works/test/a.out)
==2326== Address 0x4021228 is 0 bytes inside a block of size 1 free‘d
==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
==2326== by 0x8048509: mem_double_free (in /home/fgao/works/test/a.out)
==2326== by 0x804855D: main (in /home/fgao/works/test/a.out)
==2326==
/* 這里檢測(cè)到了未初始化變量 */
==2326== Conditional jump or move depends on uninitialised value(s)
==2326== at 0x40057B6: free (vg_replace_malloc.c:325)
==2326== by 0x804853C: mem_free_wild_pointer (in /home/fgao/works/test/a.out)
==2326== by 0x8048562: main (in /home/fgao/works/test/a.out)
==2326==
/* 這里檢測(cè)到了非法是否野指針 */
==2326== Invalid free() / delete / delete[]
==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
==2326== by 0x804853C: mem_free_wild_pointer (in /home/fgao/works/test/a.out)
==2326== by 0x8048562: main (in /home/fgao/works/test/a.out)
==2326== Address 0x4021228 is 0 bytes inside a block of size 1 free’d
==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
==2326== by 0x8048509: mem_double_free (in /home/fgao/works/test/a.out)
==2326== by 0x804855D: main (in /home/fgao/works/test/a.out)
==2326==
==2326==
/*
這里檢測(cè)到了文件指針資源的泄露,下面提示說(shuō)有4個(gè)文件描述符在退出時(shí)仍是打開(kāi)的。
描述符0,1,2無(wú)需關(guān)心,通過(guò)報(bào)告,可以發(fā)現(xiàn)程序中自己明確打開(kāi)的文件描述符沒(méi)有關(guān)閉。
*/
==2326== FILE DESCRIPTORS: 4 open at exit.
==2326== Open file descriptor 3: test.txt
==2326== at 0x68D613: __open_nocancel (in /lib/libc-2.12.so)
==2326== by 0x61F8EC: __fopen_internal (in /lib/libc-2.12.so)
==2326== by 0x61F94B: fopen@@GLIBC_2.1 (in /lib/libc-2.12.so)
==2326== by 0x8048496: mem_leak2 (in /home/fgao/works/test/a.out)
==2326== by 0x804854E: main (in /home/fgao/works/test/a.out)
==2326==
==2326== Open file descriptor 2: /dev/pts/4
==2326==
==2326==
==2326== Open file descriptor 1: /dev/pts/4
==2326==
==2326==
==2326== Open file descriptor 0: /dev/pts/4
==2326==
==2326==
==2326==
/* 堆信息的總結(jié):一共調(diào)用4次alloc,4次free。之所以正好相等,因?yàn)樯厦嬗幸缓瘮?shù)少了free,有一個(gè)函數(shù)多了一個(gè)free */
==2326== HEAP SUMMARY:
==2326== in use at exit: 353 bytes in 2 blocks
==2326== total heap usage: 4 allocs, 4 frees, 355 bytes allocated
==2326==
/* 檢測(cè)到一個(gè)字節(jié)的內(nèi)存泄露 */
==2326== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==2326== at 0x4005BDC: malloc (vg_replace_malloc.c:195)
==2326== by 0x8048475: mem_leak1 (in /home/fgao/works/test/a.out)
==2326== by 0x8048549: main (in /home/fgao/works/test/a.out)
==2326==
/* 內(nèi)存泄露的總結(jié) */
==2326== LEAK SUMMARY:
==2326== definitely lost: 1 bytes in 1 blocks
==2326== indirectly lost: 0 bytes in 0 blocks
==2326== possibly lost: 0 bytes in 0 blocks
==2326== still reachable: 352 bytes in 1 blocks
==2326== suppressed: 0 bytes in 0 blocks
==2326== Reachable blocks (those to which a pointer was found) are not shown.
==2326== To see them, rerun with: --leak-check=full --show-reachable=yes
==2326==
==2326== For counts of detected and suppressed errors, rerun with: -v
==2326== Use --track-origins=yes to see where uninitialised values come from
==2326== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 12 from 8)
這個(gè)只是一個(gè)簡(jiǎn)單的示例程序,即使沒(méi)有Valgrind,我們也可以很輕易的發(fā)現(xiàn)問(wèn)題。但是在真實(shí)的項(xiàng)目中,當(dāng)代碼量達(dá)到萬(wàn)行,十萬(wàn)行,甚至百 萬(wàn)行時(shí)。由于申請(qǐng)的內(nèi)存可能不是在一個(gè)地方使用,不可避免的被傳來(lái)傳去。這時(shí),如果光是看review代碼來(lái)檢查問(wèn)題,可能很難找到根本原因。這時(shí),使用 Valgrind則可以很容易的發(fā)現(xiàn)問(wèn)題所在。
以上就是Linux系統(tǒng)中怎么使用valgrind檢查內(nèi)存的介紹了,當(dāng)然還有一些錯(cuò)誤時(shí)valgrind檢查不到的,用戶(hù)應(yīng)該盡量避免出現(xiàn)太多的錯(cuò)誤。
發(fā)表評(píng)論
共0條
評(píng)論就這些咯,讓大家也知道你的獨(dú)特見(jiàn)解
立即評(píng)論以上留言?xún)H代表用戶(hù)個(gè)人觀點(diǎn),不代表系統(tǒng)之家立場(chǎng)