作者:spch2008
来源:优快云
原文:https://blog.youkuaiyun.com/spch2008/article/details/51375407
参数配置
gcc
- -g : 增加调试信息,供 valgrind 精准定位。
- -oo : 关闭 gcc 优,优化产生的代码可能会造成 valgring 误判。
valgrind
--leak-check = full
no : 不进行内存泄漏检测;yes : 显示内存泄漏情况;full : 显示内存泄漏和出错代码;
--show-reachable = yes
详细显示 still reachable 和 indirectly lost 两种类型的内心泄漏,默认不显示;、
内存泄漏
内存泄漏 : 由于疏忽和错误造成程序未能释放已经不能再使用的内存。
泄漏类型
possibly lost : 指针指向内存的内存位置
still reachable : 程序运行结束后,内存没有释放,仍然可以访问。
definitely lost:内存无法访问
indirectly lost:虽然有地址指向该空间,但是无法访问
泄漏举例
Pointer chain AAA Leak Case BBB Leak Case ------------------------------ --------------- ------------- (1) RRR ----------------------> BBB DR (2) RRR -------> AAA ---------> BBB DR IR (3) RRR BBB DL (4) RRR AAA ---------> BBB DL IL (5) RRR ----------?-----------> BBB (y)DR, (n)DL (6) RRR -------> AAA ----?----> BBB DR (y)IR, (n)DL (7) RRR ---?---> AAA ---------> BBB (y)DR, (n)DL (y)IR, (n)IL (8) RRR ---?---> AAA ----?----> BBB (y)DR, (n)DL (y,y)IR, (n,y)IL, (_,n)DL (9) RRR AAA ----?----> BBB DL (y)IL, (n)DL Pointer chain legend: - RRR: a root set node or DR block - AAA, BBB: heap blocks - --->: a start-pointer - -?->: an interior-pointer Leak Case legend: - DR: Directly reachable - IR: Indirectly reachable - DL: Directly lost - IL: Indirectly lost - (y)XY: it's XY if the interior-pointer is a real pointer - (n)XY: it's XY if the interior-pointer is not a real pointer - (_)XY: it's XY in either case
case 1:RRR ----> BBB
void *RRR; int main() { RRR = malloc(8); return 0; }
==1244== LEAK SUMMARY:
==1244== still reachable : 8 bytes in blocks
cas2 :RRR ----> AAA ----> BBB
void **RRR; int main() { RRR = (void **)malloc(8); *RRR = malloc(8); return 0; }
==1345== LEAK SUMMARY:
==1345== still reachable: 16 bytes in 2 blocks
case 3:RRR BBB
int main() { void *RRR = malloc(8); return 0; }
==1400== LEAK SUMMARY:
==1400== definitely lost: 8 bytes in 1 blocks
case4: RRR AAA ------> BBB
int main() { void **RRR = (void**)malloc(8); *RRR = malloc(8); return 0; }
==1461== LEAK SUMMARY:
==1461== definitely lost: 8 bytes in 1 blocks;
==1461== indirectly lost: 8 bytes in 1 blocks;
case 5: RRR ----?-----> BBB
void *RRR; int main() { RRR = malloc(8); RRR = (char *)RRR + 2; return 0; }
==1530== LEAK SUMMARY:
==1530== possibly lost: 8bytes in 1 blocks;
case6: RRR -----> AAA ---?---> BBB
void **RRR; int main() { RRR = (void**)malloc(8); *RRR = malloc(8); *RRR = (char *)(*RRR) + 2; return 0; }
==1587== LEAK SUMMARAY;
==1587== possibly lost: 8 bytes in 1 blocks;
==1587== still reachable: 8 bytes in 1 blocks;
case 7: RRR ---?---> AAA ----> BBB
void **RRR; int main() { RRR = (void **)malloc(8); *RRR = malloc(8); RRR = (void **)((char *)RRR + 1); return 0; }
==1642== LEAK SUMMARY:
==1642== possibly lost: 16 bytes in 2 blocks;
case8: RRR ---?---> AAA ---?---> BBB
void **RRR; int main() { RRR = (void **)malloc(8); *RRR = malloc(8); *RRR = ((char*)(*RRR) + 1); RRR = (void**)((char*)RRR + 1); return 0; }
==1776== LEAK SUMMARY:
==1776== possibly lost: 16 bytes in 2 blocks;
case 9:RRR AAA ---?---> BBB
int main() { void **RRR = (void**)malloc(8); *RRR = malloc(8); *RRR = ((char*)(*RRR) + 1); return 0; }
==3856== LEAK SUMMARY:
==3856== definitely lost: 8 bytes in 1 blocks;
==3856== indirectly lost: 8 bytes in 1 blocks;
内存错误
读写越界
int *arr = new int[2]; arr[2] = 2; arr[0] = arr[2]; delete [] arr;
==2371== Invalid write of size 4
==2371== at 0x80485FD: main(test.c:2)
==2371==
==2371== Invalid write of size 4
==2371== at 0x8048607: main(test.c:3)
注意: 如果在栈空间上申请数组 arr ,valgrind 则检测不出读写越界
地址重叠
char *str = new char[10]; char *src = str; char *dst = str + 2; memcpy(dst, src, 4); delete [] str;
==2413== Source and destination overlap in memcpy(0x4339902a, 0x4339028, 4)
==2413=== at 0x402EE13: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.s0)
==2413== by 0x8048654: main(test.c:4)
多次释放
char *str = new char[10]; char *rep = str; delete[] str; delete[] rep;
==2440== Invalid free() / delete / delete[] / realloc()
==2440== at 0x402BD38: operator delete
==2440== by 0x8048623: main (test.c:5)
==2440== Address 0x4339028 is 0 bytes inside a block of size 10 free
==2440== at 0x402BD38: operator delete
==2440== by 0x8048610: main (test.c:4)
==2440== HEAP SUMMARY:
==2440== in use ar exit: 0 bytest in 0 blocks
==2440== total heap usage: 1 allocs, 2 frees , 10 bytes allocated
释放内部指针
int main() { void *RRR = malloc(10); RRR = (char *)RRR + 1; free(RRR); return 0; }
==3953== HEAP SUMMARy:
==3953== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3953== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3953== by 0x804861: main(test.c:6)
==3953==
==3953== LEAK SUMMARY:
==3953== definitely lost: 10 bytes in 1 blocks
分配与释放函数不一致
int *arr= new int[10]; free(arr);
==2519== Mismatched free() / delete / delete[]
==2519== at 0x402B3D8: free
==2519== by 0x8048601: main(test.c:3)
==2519== Address 0x4339028 is 0 bytes inside a block of size 40 alloc
==2519== at 0x402ADFC: operator new
==2519== by 0x80485F1: main (test.c:1)
原理简述
valgrind memcheck 在内部模拟一个 CPU 环境,所有的数据处理流程都在内部CPU进行模拟。