C 语言学习——Valgrind 内存问题简述

作者:spch2008 
来源:CSDN 
原文:https://blog.csdn.net/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进行模拟。

 

posted @ 2019-04-26 16:54  木叶苍蓝  阅读(506)  评论(0编辑  收藏  举报