內(nèi)存泄漏檢測神器valgrind


title: 內(nèi)存泄漏檢測神器valgrind

categories:[內(nèi)存檢測]

tags:[valgrind]

date: 2022/01/08

作者:hackett

微信公眾號:加班猿


1.概述

Valgrind是一款用于內(nèi)存調(diào)試画饥、內(nèi)存泄漏檢測以及性能分析的軟件開發(fā)工具饭于。

Valgrind 發(fā)行版目前包括七個生產(chǎn)質(zhì)量工具:一個內(nèi)存錯誤檢測器裆操、兩個線程錯誤檢測器茄茁、一個緩存和分支預測分析器、一個調(diào)用圖生成緩存和分支預測分析器巷蚪,以及兩個不同的堆分析器帮孔。它還包括一個實驗性的 SimPoint 基本塊矢量生成器克胳。它可在以下平臺上運行:X86/Linux德挣、AMD64/Linux恭垦、ARM/Linux、ARM64/Linux格嗅、PPC32/Linux番挺、PPC64/Linux、PPC64LE/Linux吗浩、S390X/Linux建芙、MIPS32/Linux、MIPS64/Linux懂扼、X86/Solaris , AMD64/Solaris, ARM/Android (2.3.x 及更高版本), ARM64/Android, X86/Android (4.0 及更高版本), MIPS32/Android, X86/FreeBSD, AMD64/FreeBSD, X86/Darwin 和 AMD64/Darwin (Mac OS X 10.12)

1.1 工具

它一般包含下列工具:

1.Memcheck

最常用的工具,用來檢測程序中出現(xiàn)的內(nèi)存問題右蒲,所有對內(nèi)存的讀寫都會被檢測到阀湿,一切對malloc()/free()/new/delete的調(diào)用都會被捕獲。所以瑰妄,它能檢測以下問題:

  • 對未初始化內(nèi)存的使用陷嘴;

  • 讀/寫釋放后的內(nèi)存塊;

  • 讀/寫超出malloc分配的內(nèi)存塊间坐;

  • 讀/寫不適當?shù)臈V袃?nèi)存塊灾挨;

  • 內(nèi)存泄漏,指向一塊內(nèi)存的指針永遠丟失竹宋;

  • 不正確的malloc/free或new/delete匹配劳澄;

  • memcpy()相關函數(shù)中的dst和src指針重疊。

2.Callgrind

和gprof類似的分析工具蜈七,但它對程序的運行觀察更是入微秒拔,能給我們提供更多的信息。和gprof不同飒硅,它不需要在編譯源代碼時附加特殊選項砂缩,但加上調(diào)試選項是推薦的。Callgrind收集程序運行時的一些數(shù)據(jù)三娩,建立函數(shù)調(diào)用關系圖庵芭,還可以有選擇地進行cache模擬。在運行結束時雀监,它會把分析數(shù)據(jù)寫入一個文件双吆。callgrind_annotate可以把這個文件的內(nèi)容轉化成可讀的形式。

3.Cachegrind

Cache分析器,它模擬CPU中的一級緩存I1伊诵,Dl和二級緩存单绑,能夠精確地指出程序中cache的丟失和命中。如果需要曹宴,它還能夠為我們提供cache丟失次數(shù)搂橙,內(nèi)存引用次數(shù),以及每行代碼笛坦,每個函數(shù)区转,每個模塊,整個程序產(chǎn)生的指令數(shù)版扩。這對優(yōu)化程序有很大的幫助废离。

4.Helgrind

它主要用來檢查多線程程序中出現(xiàn)的競爭問題。Helgrind尋找內(nèi)存中被多個線程訪問礁芦,而又沒有一貫加鎖的區(qū)域蜻韭,這些區(qū)域往往是線程之間失去同步的地方,而且會導致難以發(fā)掘的錯誤柿扣。Helgrind實現(xiàn)了名為“Eraser”的競爭檢測算法肖方,并做了進一步改進,減少了報告錯誤的次數(shù)未状。不過俯画,Helgrind仍然處于實驗階段。

5.Massif

堆棧分析器司草,它能測量程序在堆棧中使用了多少內(nèi)存艰垂,告訴我們堆塊,堆管理塊和棧的大小埋虹。Massif能幫助我們減少內(nèi)存的使用猜憎,在帶有虛擬內(nèi)存的現(xiàn)代系統(tǒng)中,它還能夠加速我們程序的運行吨岭,減少程序停留在交換區(qū)中的幾率拉宗。
此外,lackey和nulgrind也會提供辣辫。Lackey是小型工具旦事,很少用到;Nulgrind只是為開發(fā)者展示如何創(chuàng)建一個工具急灭。

1.2原理

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

Valid-Value 表

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

Valid-Address 表

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

檢測原理:

當要讀寫內(nèi)存中某個字節(jié)時,首先檢查這個字節(jié)對應的 A bit亏钩。如果該A bit顯示該位置是無效位置莲绰,memcheck則報告讀寫錯誤。
內(nèi)核(core)類似于一個虛擬的 CPU 環(huán)境姑丑,這樣當內(nèi)存中的某個字節(jié)被加載到真實的 CPU 中時蛤签,該字節(jié)對應的 V bit 也被加載到虛擬的 CPU 環(huán)境中。一旦寄存器中的值栅哀,被用來產(chǎn)生內(nèi)存地址震肮,或者該值能夠影響程序輸出,則 memcheck 會檢查對應的V bits昌屉,如果該值尚未初始化钙蒙,則會報告使用未初始化內(nèi)存錯誤。

2.安裝使用

2.1下載

去官網(wǎng)https://valgrind.org/下載最新版本

centos下載:

yum install valgrind

Ubuntu下載

sudo apt-get install valgrind

2.2使用

用法:valgrind[options] prog-and-args [options]:

常用選項间驮,適用于所有Valgrind工具

-tool=<name> 最常用的選項。運行 valgrind中名為toolname的工具马昨。默認memcheck竞帽。
h –help 顯示幫助信息。

-version 顯示valgrind內(nèi)核的版本鸿捧,每個工具都有各自的版本屹篓。

q –quiet 安靜地運行,只打印錯誤信息匙奴。

v –verbose 更詳細的信息, 增加錯誤數(shù)統(tǒng)計堆巧。

-trace-children=no|yes 跟蹤子線程? [no]

-track-fds=no|yes 跟蹤打開的文件描述?[no]

-time-stamp=no|yes 增加時間戳到LOG信息? [no]

-log-fd=<number> 輸出LOG到描述符文件 [2=stderr]

-log-file=<file> 將輸出的信息寫入到filename.PID的文件里泼菌,PID是運行程序的進行ID

-log-file-exactly=<file> 輸出LOG信息到 file

-log-file-qualifier=<VAR> 取得環(huán)境變量的值來做為輸出信息的文件名谍肤。 [none]

-log-socket=ipaddr:port 輸出LOG到socket ,ipaddr:port

LOG信息輸出:

-xml=yes 將信息以xml格式輸出哗伯,只有memcheck可用

-num-callers=<number> show <number> callers in stack traces [12]

-error-limit=no|yes 如果太多錯誤荒揣,則停止顯示新錯誤? [yes]

-error-exitcode=<number> 如果發(fā)現(xiàn)錯誤則返回錯誤代碼 [0=disable]

-db-attach=no|yes 當出現(xiàn)錯誤,valgrind會自動啟動調(diào)試器gdb焊刹。[no]

-db-command=<command> 啟動調(diào)試器的命令行選項[gdb -nw %f %p]

適用于Memcheck工具的相關選項:

-leak-check=no|summary|full 要求對leak給出詳細信息? [summary]

-leak-resolution=low|med|high how much bt merging in leak check [low]

-show-reachable=no|yes show reachable blocks in leak check? [no]

3.應用例子

3.1數(shù)組越界

malloc1.c

#include <stdio.h>
  
int main(int argc, char **argv) {

    int *x = malloc(8*sizeof(int));

    x[9] = 0; // 數(shù)組下標越界

    free(x);
    return 0;
}

編譯:

gcc -Wall malloc1.c -g -o malloc1

使用Valgrind檢查程序BUG:

# --leak-check=full 所有泄露檢查
valgrind --tool=memcheck --leak-check=full ./malloc1

運行結果:

[root@hackett valgrind]# valgrind --tool=memcheck --leak-check=full ./malloc1
==550168== Memcheck, a memory error detector
==550168== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==550168== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==550168== Command: ./malloc1
==550168== 
==550168== Invalid write of size 4
==550168==    at 0x4005FB: main (malloc1.c:7)
==550168==  Address 0x520b064 is 4 bytes after a block of size 32 alloc'd
==550168==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550168==    by 0x4005EE: main (malloc1.c:5)
==550168== 
==550168== 
==550168== HEAP SUMMARY:
==550168==     in use at exit: 0 bytes in 0 blocks
==550168==   total heap usage: 1 allocs, 1 frees, 32 bytes allocated
==550168== 
==550168== All heap blocks were freed -- no leaks are possible
==550168== 
==550168== For lists of detected and suppressed errors, rerun with: -s
==550168== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

分析:

1系任、每一行開頭的數(shù)字代表是進程ID恳蹲,這里的進程ID為550168

2、==550168== Invalid write of size 4
==550168== at 0x4005BB: main (malloc1.c:7)

這兩行顯示的是錯誤出現(xiàn)的位置俩滥,就是 x 分配了 10 byte 的空間嘉蕾,但是向第 11 個 byte 寫數(shù)據(jù), 所以就會顯示 Invalid write 的錯誤,代碼在malloc1.c的第7行

3.2內(nèi)存釋放后進行讀寫

malloc2.c

#include <stdio.h>
  
int main(int argc, char **argv) {

    char *p = malloc(1);

    *p = 'a';

    char c = *p;

    printf("[%c]\n",c);

    free(p); // 釋放

    c = *p; //取值 讀

    return 0;
}

編譯:

gcc -Wall malloc2.c -g -o malloc2

使用Valgrind檢查程序BUG:

# --leak-check=full 所有泄露檢查
valgrind --tool=memcheck --leak-check=full ./malloc2

運行結果:

[root@hackett valgrind]# valgrind --tool=memcheck --leak-check=full ./malloc2
==550063== Memcheck, a memory error detector
==550063== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==550063== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==550063== Command: ./malloc2
==550063== 
[a]
==550063== Invalid read of size 1
==550063==    at 0x400679: main (malloc2.c:15)
==550063==  Address 0x520b040 is 0 bytes inside a block of size 1 free'd
==550063==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550063==    by 0x400674: main (malloc2.c:13)
==550063==  Block was alloc'd at
==550063==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550063==    by 0x40063E: main (malloc2.c:5)
==550063== 
==550063== 
==550063== HEAP SUMMARY:
==550063==     in use at exit: 0 bytes in 0 blocks
==550063==   total heap usage: 2 allocs, 2 frees, 1,025 bytes allocated
==550063== 
==550063== All heap blocks were freed -- no leaks are possible
==550063== 
==550063== For lists of detected and suppressed errors, rerun with: -s
==550063== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

分析:

1霜旧、每一行開頭的數(shù)字代表是進程ID错忱,這里的進程ID為550063

2、==550063== Invalid read of size 1
==550063== at 0x400679: main (malloc2.c:15)
==550063== Address 0x520b040 is 0 bytes inside a block of size 1 free'd
==550063== at 0x4C38A03: free (vg_replace_malloc.c:755)
==550063== by 0x400674: main (malloc2.c:13)

這五行顯示的是錯誤出現(xiàn)的位置颁糟,就是 p指向的內(nèi)存已經(jīng)釋放了航背,還對其進行讀操作,所以就會顯示 Invalid read 的錯誤棱貌,代碼在malloc2.c的第15行

3.3無效讀寫

malloc3.c

#include <stdio.h>
  
int main(int argc, char **argv) {

    char *p = malloc(1);

    *p = 'a';

    char c = *(p+1); // 地址加1 無效讀

    printf("[%c]\n",c);

    free(p); // 釋放
    
    return 0;
}

編譯:

gcc -Wall malloc3.c -g -o malloc3

使用Valgrind檢查程序BUG:

# --leak-check=full 所有泄露檢查
valgrind --tool=memcheck --leak-check=full ./malloc3

運行結果:

[root@iZwz97bu0gr8vx0j8l6kkzZ valgrind]# valgrind --tool=memcheck --leak-check=full ./malloc3
==550135== Memcheck, a memory error detector
==550135== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==550135== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==550135== Command: ./malloc3
==550135== 
==550135== Invalid read of size 1
==550135==    at 0x40064E: main (malloc3.c:9)
==550135==  Address 0x520b041 is 0 bytes after a block of size 1 alloc'd
==550135==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550135==    by 0x40063E: main (malloc3.c:5)
==550135== 
[]
==550135== 
==550135== HEAP SUMMARY:
==550135==     in use at exit: 0 bytes in 0 blocks
==550135==   total heap usage: 2 allocs, 2 frees, 1,025 bytes allocated
==550135== 
==550135== All heap blocks were freed -- no leaks are possible
==550135== 
==550135== For lists of detected and suppressed errors, rerun with: -s
==550135== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

分析:

1玖媚、每一行開頭的數(shù)字代表是進程ID,這里的進程ID為550135

2婚脱、==550135== Invalid read of size 1
==550135== at 0x40064E: main (malloc3.c:9)

這五行顯示的是錯誤出現(xiàn)的位置今魔,就是對未分配內(nèi)存的空間進行讀取,所以就會顯示 Invalid read 的錯誤障贸,代碼在malloc3.c的第9行

3.4內(nèi)存泄漏

malloc4.c

#include <stdio.h>
  
int main(int argc, char **argv) {

    char *p = malloc(1);

    *p = 'a';

    char c = *p; 

    printf("[%c]\n",c); // 申請后沒有釋放p 內(nèi)存泄漏


    return 0;
}

編譯:

gcc -Wall malloc4.c -g -o malloc4

使用Valgrind檢查程序BUG:

# --leak-check=full 所有泄露檢查
valgrind --tool=memcheck --leak-check=full ./malloc4

運行結果:

[root@hackett valgrind]# valgrind --tool=memcheck --leak-check=full ./malloc4
==550195== Memcheck, a memory error detector
==550195== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==550195== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==550195== Command: ./malloc4
==550195== 
[a]
==550195== 
==550195== HEAP SUMMARY:
==550195==     in use at exit: 1 bytes in 1 blocks
==550195==   total heap usage: 2 allocs, 1 frees, 1,025 bytes allocated
==550195== 
==550195== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==550195==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550195==    by 0x4005EE: main (malloc4.c:5)
==550195== 
==550195== LEAK SUMMARY:
==550195==    definitely lost: 1 bytes in 1 blocks
==550195==    indirectly lost: 0 bytes in 0 blocks
==550195==      possibly lost: 0 bytes in 0 blocks
==550195==    still reachable: 0 bytes in 0 blocks
==550195==         suppressed: 0 bytes in 0 blocks
==550195== 
==550195== For lists of detected and suppressed errors, rerun with: -s
==550195== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

分析:

1错森、每一行開頭的數(shù)字代表是進程ID,這里的進程ID為550195

2篮洁、==550195== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==550195== at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550195== by 0x4005EE: main (malloc4.c:5)

這三行顯示的是錯誤出現(xiàn)的位置涩维,是 stack trace內(nèi)存泄漏,代碼在malloc1.c的第5行袁波,申請了內(nèi)存沒有進行對應的free

3.5內(nèi)存多次釋放

malloc5.c

#include <stdio.h>
  
int main(int argc, char **argv) {

    char *p = malloc(1);

    *p = 'a';

    char c = *p; // 地址加1

    printf("[%c]\n",c);

    free(p);
    free(p);// 內(nèi)存多次釋放
    free(p);// 內(nèi)存多次釋放

    return 0;
}

編譯:

gcc -Wall malloc5.c -g -o malloc5

使用Valgrind檢查程序BUG:

# --leak-check=full 所有泄露檢查
valgrind --tool=memcheck --leak-check=full ./malloc5

運行結果:

[root@hackett valgrind]# valgrind --tool=memcheck --leak-check=full ./malloc5
==550227== Memcheck, a memory error detector
==550227== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==550227== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==550227== Command: ./malloc5
==550227== 
[a]
==550227== Invalid free() / delete / delete[] / realloc()
==550227==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550227==    by 0x400680: main (malloc5.c:14)
==550227==  Address 0x520b040 is 0 bytes inside a block of size 1 free'd
==550227==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550227==    by 0x400674: main (malloc5.c:13)
==550227==  Block was alloc'd at
==550227==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550227==    by 0x40063E: main (malloc5.c:5)
==550227== 
==550227== Invalid free() / delete / delete[] / realloc()
==550227==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550227==    by 0x40068C: main (malloc5.c:15)
==550227==  Address 0x520b040 is 0 bytes inside a block of size 1 free'd
==550227==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550227==    by 0x400674: main (malloc5.c:13)
==550227==  Block was alloc'd at
==550227==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550227==    by 0x40063E: main (malloc5.c:5)
==550227== 
==550227== 
==550227== HEAP SUMMARY:
==550227==     in use at exit: 0 bytes in 0 blocks
==550227==   total heap usage: 2 allocs, 4 frees, 1,025 bytes allocated
==550227== 
==550227== All heap blocks were freed -- no leaks are possible
==550227== 
==550227== For lists of detected and suppressed errors, rerun with: -s
==550227== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

分析:

1瓦阐、每一行開頭的數(shù)字代表是進程ID,這里的進程ID為550227

2篷牌、==550227== Invalid free() / delete / delete[] / realloc()
==550227== at 0x4C38A03: free (vg_replace_malloc.c:755)
==550227== by 0x400680: main (malloc5.c:14)

這三行顯示的是第一個錯誤出現(xiàn)的位置睡蟋,就是多次釋放內(nèi)存問題, 所以就會顯示 Invalid free() / delete / delete[] / realloc() 的錯誤,代碼在malloc5.c的第14行

3枷颊、==550227== Invalid free() / delete / delete[] / realloc()
==550227== at 0x4C38A03: free (vg_replace_malloc.c:755)
==550227== by 0x40068C: main (malloc5.c:15)

這三行顯示的是第二個錯誤出現(xiàn)的位置戳杀,就是多次釋放內(nèi)存問題, 所以就會顯示 Invalid free() / delete / delete[] / realloc() 的錯誤,代碼在malloc5.c的第15行

3.6動態(tài)內(nèi)存管理

常見的內(nèi)存分配方式分三種:靜態(tài)存儲夭苗,棧上分配信卡,堆上分配。全局變量屬于靜態(tài)存儲听诸,它們是在編譯時就被分配了存儲空間坐求,函數(shù)內(nèi)的局部變量屬于棧上分配,而最靈活的內(nèi)存使用方式當屬堆上分配晌梨,也叫做內(nèi)存動態(tài)分配了桥嗤。常用的內(nèi)存動態(tài)分配函數(shù)包括:malloc, alloc, realloc, new等须妻,動態(tài)釋放函數(shù)包括free, delete。

一旦成功申請了動態(tài)內(nèi)存泛领,我們就需要自己對其進行內(nèi)存管理荒吏,而這又是最容易犯錯誤的。

malloc6.c

#include <stdio.h>
// 內(nèi)存動態(tài)管理

int main(int argc, char **argv) {

    int i;
    char *p = (char *)malloc(10);

    char *pt = p;
    for(i = 0; i < 10; i++) {
        p[i] = 'A'+i;
    }

    free(p);

    pt[1] = 'x';

    free(pt);

    return 0;
}

編譯:

gcc -Wall malloc6.c -g -o malloc6

使用Valgrind檢查程序BUG:

# --leak-check=full 所有泄露檢查
valgrind --tool=memcheck --leak-check=full ./malloc6

運行結果:

[root@hackett valgrind]# valgrind --tool=memcheck --leak-check=full ./malloc6
==550239== Memcheck, a memory error detector
==550239== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==550239== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==550239== Command: ./malloc6
==550239== 
==550239== Invalid write of size 1
==550239==    at 0x400639: main (malloc6.c:16)
==550239==  Address 0x520b041 is 1 bytes inside a block of size 10 free'd
==550239==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550239==    by 0x400630: main (malloc6.c:14)
==550239==  Block was alloc'd at
==550239==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550239==    by 0x4005EE: main (malloc6.c:7)
==550239== 
==550239== Invalid free() / delete / delete[] / realloc()
==550239==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550239==    by 0x400647: main (malloc6.c:18)
==550239==  Address 0x520b040 is 0 bytes inside a block of size 10 free'd
==550239==    at 0x4C38A03: free (vg_replace_malloc.c:755)
==550239==    by 0x400630: main (malloc6.c:14)
==550239==  Block was alloc'd at
==550239==    at 0x4C360A5: malloc (vg_replace_malloc.c:380)
==550239==    by 0x4005EE: main (malloc6.c:7)
==550239== 
==550239== 
==550239== HEAP SUMMARY:
==550239==     in use at exit: 0 bytes in 0 blocks
==550239==   total heap usage: 1 allocs, 2 frees, 10 bytes allocated
==550239== 
==550239== All heap blocks were freed -- no leaks are possible
==550239== 
==550239== For lists of detected and suppressed errors, rerun with: -s
==550239== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

分析:

1渊鞋、每一行開頭的數(shù)字代表是進程ID绰更,這里的進程ID為550239

2、==550239== Invalid write of size 1
==550239== at 0x400639: main (malloc6.c:16)

這一行顯示這里有一個錯誤锡宋,就是發(fā)生非法寫操作, 所以就會顯示 Invalid write 的錯誤儡湾,代碼在malloc6.c的第16行

3、==550239== Invalid free() / delete / delete[] / realloc()
==550239== at 0x4C38A03: free (vg_replace_malloc.c:755)
==550239== by 0x400647: main (malloc6.c:18)
==550239== Address 0x520b040 is 0 bytes inside a block of size 10 free'd
==550239== at 0x4C38A03: free (vg_replace_malloc.c:755)
==550239== by 0x400630: main (malloc6.c:14)

這五行顯示的是第二個錯誤出現(xiàn)的位置执俩,指針p和pt指向的是同一塊內(nèi)存徐钠,卻被先后釋放兩次。系統(tǒng)會在堆上維護一個動態(tài)內(nèi)存鏈表役首,如果被釋放尝丐,就意味著該塊內(nèi)存可以繼續(xù)被分配給其他部分,如果內(nèi)存被釋放后再訪問衡奥,就可能覆蓋其他部分的信息爹袁,這是一種嚴重的錯誤,上述程序第16行中就在釋放后仍然寫這塊內(nèi)存矮固。

總結:

1.申請內(nèi)存在使用完成后就要釋放失息。如果沒有釋放,或少釋放了就是內(nèi)存泄露档址;多釋放也會產(chǎn)生問題根时。

2.注意數(shù)組的大小,別越界讀寫訪問非法內(nèi)存

3.malloc和new要對應free和delete使用辰晕。

如果你覺得文章還不錯,可以給個"三連"确虱,文章同步到個人微信公眾號[加班猿]

我是hackett含友,我們下期見

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市校辩,隨后出現(xiàn)的幾起案子窘问,更是在濱河造成了極大的恐慌,老刑警劉巖宜咒,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惠赫,死亡現(xiàn)場離奇詭異,居然都是意外死亡故黑,警方通過查閱死者的電腦和手機儿咱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門庭砍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人混埠,你說我怎么就攤上這事怠缸。” “怎么了钳宪?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵揭北,是天一觀的道長。 經(jīng)常有香客問我吏颖,道長搔体,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任半醉,我火速辦了婚禮疚俱,結果婚禮上,老公的妹妹穿的比我還像新娘奉呛。我一直安慰自己计螺,他們只是感情好,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般搪泳。 火紅的嫁衣襯著肌膚如雪斟湃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天敢辩,我揣著相機與錄音,去河邊找鬼。 笑死麦射,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的灯谣。 我是一名探鬼主播潜秋,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胎许!你這毒婦竟也來了峻呛?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤辜窑,失蹤者是張志新(化名)和其女友劉穎钩述,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體穆碎,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡牙勘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了所禀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片方面。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡放钦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出葡幸,到底是詐尸還是另有隱情最筒,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布蔚叨,位于F島的核電站床蜘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蔑水。R本人自食惡果不足惜邢锯,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搀别。 院中可真熱鬧丹擎,春花似錦、人聲如沸歇父。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽榜苫。三九已至护戳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間垂睬,已是汗流浹背媳荒。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留驹饺,地道東北人钳枕。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像赏壹,于是被迫代替她去往敵國和親鱼炒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

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