c/c++的內存管理一直都是程序猿最頭痛的事情,內存越界、數組越界、內存泄漏、內存溢出、野指針、空指針..., 隨便一個問題均可能讓程序崩潰。並且每每問題的源頭都比較隱蔽,讓人很難排查出問題的根源所在。
想要解決這個問題,還得從問題的根源入手。valgrind是一個強大的內存管理工具,經常使用來檢測內存泄漏和內存的非法使用,用好了能夠很好的從根源上解決c/c++內存管理的問題。linux
virgrind能夠用來檢測程序開發中的絕大多數內存,函數、緩存使用、多線程競爭訪問內存、堆棧問題,是一個linux下功能很是強大內存檢測工具。c++
valgrind-tool=<name> 最經常使用的選項。運行valgrind中名爲toolname的工具。默認memcheck。數組
memcheck:這是valgrind應用最普遍的工具,一個重量級的內存檢查器,可以發現開發中絕大多數內存錯誤問題,好比:使用未初始化的內存,使用已經釋放了的內存,內存訪問越界等。下面將重點介紹此功能。緩存
callgrind: 主要用來檢查程序中函數調用過程當中出現的問題。多線程
cachegrind: 主要用來檢查程序中緩存使用出現的問題。socket
helgrind: 主要用來檢查多線程程序中出現的競爭問題。ide
massif: 主要用來檢查程序中堆棧使用中出現的問題。函數
extension: 能夠利用core提供的功能,本身編寫特定的內存調試工具。工具
valid-value表:
對於進程的整個地址空間中的每個字節(byte),都有與之對應的8個bits,對於CPU的每一個寄存器,也有一個與之對應的bit向量。這些bits負責記錄該字節或者寄存器值是否具備有效的、已經初始化的值。
valid-Address表:
對於進程整個地址空間中的一個字節(byte),還有與之對應的1bit,負責記錄該地址是否可以被讀寫。
內存檢測原理:
當要讀寫內存中的某個字節時,首先檢查這個字節對應的address bit。若是該address bit顯示該位置是無效位置,memcheck則報告內存讀寫錯誤。valgrind內核至關於一個虛擬的CPU環境,當內存中的某個字節被加載到真實的CPU中時,該字節對應的value bit也被加載到虛擬的CPU環境中,一旦寄存器中的值,被用來產生內存地址,或者該值可以影響程序的輸出,則mencheck會檢查對應的value bits,若是該值還沒有初始化,則會報告使用未初始化內存錯誤。優化
建立gdbmem.cpp源碼文件,準備待檢測的代碼以下:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <malloc.h> #include<pthread.h> #include<string.h> //memory access overflow char* stringcopy(char* psrc) { int len = strlen(psrc) + 1; char* pdst = (char*)malloc(len);//12 memset(pdst, 0, len * 2);//13 memcpy(pdst, psrc, len*2);//14 return pdst; } //array assess overflow void printarray(int arry[], int arrysize) { int i = 0; for(; i < arrysize; i++) //for(i = arrysize-1; i >= 0; i--) { printf("arry[%d]:%d\n",i, arry[i]); } printf("arry[%d]:%d\n",i+1, arry[i+1]);//27 } //main body int main(int narg, const char** args) { char* pwildptr; char* pstr = "this is a memory debug program!\n"; int array[10] = {1,2,3,4,5,6,7,8,9,10}; char* ptmp = stringcopy(pstr);//36 //memory leak char* ptmp2 = (char*)malloc(100);//38 memset(ptmp2, 0, 100); // memory write overflow printf(ptmp);//41 // array tip assess overflow printarray(array, 10);//43 free(ptmp);//44 printf("%p", pwildptr);//45 //wild ptr copy memcpy(ptmp, ptmp2, 20);//47 printf(ptmp);//48 return 0; }
$g++ -g -O0 -c gdbmem.cpp#-g:編譯帶調試信息的obj文件,-O0:不優化
$g++ -o gdbmem gdbmem.o
編譯後將在當前目錄下生成gdbmem可執行文件。
valgring 對gdbmem進行內存檢測
$ valgrind --tool=memcheck --leak-check=full --track-fds=yes ./gdbmem ==10668== Memcheck, a memory error detector ==10668== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==10668== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==10668== Command: ./gdbmem ==10668== ==10668== Invalid write of size 8 ==10668== at 0x4C3453F: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid write of size 1 ==10668== at 0x4C34558: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client" ==10668== ==10668== Invalid write of size 8 ==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid write of size 2 ==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client" ==10668== this is a memory debug program! arry[0]:1 arry[1]:2 arry[2]:3 arry[3]:4 arry[4]:5 arry[5]:6 arry[6]:7 arry[7]:8 arry[8]:9 arry[9]:10 arry[11]:-623874025 ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E8890E: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Use of uninitialised value of size 8 ==10668== at 0x4E84711: _itoa_word (_itoa.c:180) ==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E84718: _itoa_word (_itoa.c:180) ==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E881AF: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E87C59: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E87CE2: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45)
main函數45行,memcpy(ptmp, ptmp2, 20);讀取已經被釋放的內存,致使memcheck報錯。
==10668== Invalid write of size 8 ==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008FE: main (gdbmem.cpp:47) ==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid write of size 2 ==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008FE: main (gdbmem.cpp:47) ==10668== Address 0x5204050 is 16 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid read of size 1 ==10668== at 0x4ED0760: strchrnul (strchr.S:24) ==10668== by 0x4E87207: __find_specmb (printf-parse.h:108) ==10668== by 0x4E87207: vfprintf (vfprintf.c:1312) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x40090F: main (gdbmem.cpp:48) ==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid read of size 1 ==10668== at 0x4E8741A: vfprintf (vfprintf.c:1324) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x40090F: main (gdbmem.cpp:48) ==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== 0x40097d==10668== ==10668== FILE DESCRIPTORS: 3 open at exit. ==10668== Open file descriptor 2: /dev/pts/4 ==10668== <inherited from parent> ==10668== ==10668== Open file descriptor 1: /dev/pts/4 ==10668== <inherited from parent> ==10668== ==10668== Open file descriptor 0: /dev/pts/4 ==10668== <inherited from parent> ==10668== ==10668== ==10668== HEAP SUMMARY: ==10668== in use at exit: 100 bytes in 1 blocks ==10668== total heap usage: 3 allocs, 2 frees, 1,157 bytes allocated ==10668== ==10668== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400888: main (gdbmem.cpp:38) ==10668== ==10668== LEAK SUMMARY: ==10668== definitely lost: 100 bytes in 1 blocks ==10668== indirectly lost: 0 bytes in 0 blocks ==10668== possibly lost: 0 bytes in 0 blocks ==10668== still reachable: 0 bytes in 0 blocks ==10668== suppressed: 0 bytes in 0 blocks ==10668== ==10668== For counts of detected and suppressed errors, rerun with: -v ==10668== Use --track-origins=yes to see where uninitialised values come from ==10668== ERROR SUMMARY: 37 errors from 15 contexts (suppressed: 0 from 0)
memcheck的LEAK SUMMARY輸出結果將內存泄漏分爲如下幾種狀況:
definitely lost:明確地已經泄漏了,由於在程序運行完的時候,沒有指針指向它, 指向它的指針在程序中丟失了
indirectly lost:間接丟失。當使用了含有指針成員的類或結構時可能會報這個錯誤。這類錯誤無需直接修復,他們老是與」definitely lost」一塊兒出現,只要修復」definitely lost」便可。
possibly lost:發現了一個指向某塊內存中部的指針,而不是指向內存塊頭部。這種指針通常是原先指向內存塊頭部,後來移動到了內存塊的中部,還有可能該指針和該內存根本就沒有關係,檢測工具只是懷疑有內存泄漏。
still reachable:能夠訪問,未丟失但也未釋放
suppressed:已被解決。出現了內存泄露但系統自動處理了。能夠無視這類錯誤。
內存泄漏概述:
==10668== LEAK SUMMARY: ==10668== definitely lost: 100 bytes in 1 blocks ==10668== indirectly lost: 0 bytes in 0 blocks ==10668== possibly lost: 0 bytes in 0 blocks ==10668== still reachable: 0 bytes in 0 blocks ==10668== suppressed: 0 bytes in 0 blocks
此處只有100個字節的內存泄漏。
==10668== Invalid write of size 8 ==10668== at 0x4C3453F: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd
根據錯誤提示,stringcopy 函數13行,即memset(pdst, 0, len 2);申請了len的數據長度,memset的時候卻使用了2len的數據長度,內存寫溢出了。
==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid write of size 1 ==10668== at 0x4C34558: memset (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x40075D: stringcopy(char*) (gdbmem.cpp:13) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client"
stringcopy 函數13行,即memset(pdst, 0, len2);申請了len的數據長度,memset的時候卻使用了2len的數據長度,內存寫溢出。相同語句的內存寫溢出,卻報了兩個錯誤,緣由筆者目前也尚未弄明白,若是有大蝦指點,不勝感激。
==10668== ==10668== Invalid write of size 8 ==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204060 is 32 bytes inside a block of size 33 alloc'd ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid write of size 2 ==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400778: stringcopy(char*) (gdbmem.cpp:14) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== Address 0x5204080 is 16 bytes after a block of size 48 in arena "client"
stringcopy 函數13行,即memcpy(pdst, psrc, len2);申請了len的數據長度,memset的時候卻使用了2len的數據長度,內存寫溢出。
==10668== this is a memory debug program! arry[0]:1 arry[1]:2 arry[2]:3 arry[3]:4 arry[4]:5 arry[5]:6 arry[6]:7 arry[7]:8 arry[8]:9 arry[9]:10 arry[11]:-623874025 ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E8890E: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Use of uninitialised value of size 8 ==10668== at 0x4E84711: _itoa_word (_itoa.c:180) ==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E84718: _itoa_word (_itoa.c:180) ==10668== by 0x4E8812C: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E881AF: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E87C59: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45) ==10668== ==10668== Conditional jump or move depends on uninitialised value(s) ==10668== at 0x4E87CE2: vfprintf (vfprintf.c:1631) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x4008E6: main (gdbmem.cpp:45)
main函數45行,printf("%p", pwildptr);讀取未初始化的野指針
==10668== ==10668== Invalid write of size 8 ==10668== at 0x4C326CB: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008FE: main (gdbmem.cpp:47) ==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid write of size 2 ==10668== at 0x4C32723: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008FE: main (gdbmem.cpp:47) ==10668== Address 0x5204050 is 16 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36)
main函數47行,memcpy(ptmp, ptmp2, 20);寫入已經釋放的內存
==10668== ==10668== Invalid read of size 1 ==10668== at 0x4ED0760: strchrnul (strchr.S:24) ==10668== by 0x4E87207: __find_specmb (printf-parse.h:108) ==10668== by 0x4E87207: vfprintf (vfprintf.c:1312) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x40090F: main (gdbmem.cpp:48) ==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36) ==10668== ==10668== Invalid read of size 1 ==10668== at 0x4E8741A: vfprintf (vfprintf.c:1324) ==10668== by 0x4E8F898: printf (printf.c:33) ==10668== by 0x40090F: main (gdbmem.cpp:48) ==10668== Address 0x5204040 is 0 bytes inside a block of size 33 free'd ==10668== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x4008D0: main (gdbmem.cpp:44) ==10668== Block was alloc'd at ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400740: stringcopy(char*) (gdbmem.cpp:12) ==10668== by 0x40087A: main (gdbmem.cpp:36)
main函數47行,printf(ptmp);寫入已經釋放的內存
0x40097d==10668== ==10668== FILE DESCRIPTORS: 3 open at exit. ==10668== Open file descriptor 2: /dev/pts/4 ==10668== <inherited from parent> ==10668== ==10668== Open file descriptor 1: /dev/pts/4 ==10668== <inherited from parent> ==10668== ==10668== Open file descriptor 0: /dev/pts/4 ==10668== <inherited from parent>
linux爲了實現一切皆文件的設計哲學,不只將數據抽象成了文件,也將一切操做和資源抽象成了文件,好比說硬件設備,socket,磁盤,進程,線程等。
這樣的設計將系統的全部動做都統一塊兒來,實現了對系統的原子化操做,大大下降了維護和操做的難度。
設備描述符,就是描述該文件數據設備的惟一標示,不一樣類型的文件,文件描述符也不同,以下所示:
==10668== ==10668== ==10668== HEAP SUMMARY: ==10668== in use at exit: 100 bytes in 1 blocks ==10668== total heap usage: 3 allocs, 2 frees, 1,157 bytes allocated ==10668== ==10668== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==10668== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10668== by 0x400888: main (gdbmem.cpp:38) ==10668==
內存泄漏概述,3次內存分配,兩次釋放。已經有100個字節的內存已經肯定泄漏。泄漏的內存分配於38行,char ptmp2 = (char)malloc(100);至此,內存泄漏檢測完畢。
valgrind對內存讀寫溢出,讀取未初始化的變量、指針、內存可以很好的檢測到,可是對於數組越界卻沒法檢測,這是由於memcheck並不對stack和全局數組進行越界檢查,因此沒法檢測出printarray中的內存訪問越界。