Valgrind检测内存管理错误

一 点睛

常见的内存分配方式分3种:静态存储、栈上分配、堆上分配。全局变量属于静态存储,它在编译时就被分配了存储空间;函数内的局部变量属于栈上分配;而最灵活的内存使用方式当属于堆上分配,也叫内存动态分配。

常用的内存动态分配函数包括:malloc 、alloc、realloc、new等,动态释放函数包括free和delete等。

一旦成功申请了动态内存,就需要自己对其进行内存管理,而这又是最容易犯错误的。

常见的错误包括:

  • 申请和释放不一致:申请和释放混用

  • 申请和释放不匹配:申请和释放的次数不匹配

  • 释放后任然读写

二 动态内存管理错误例子

#include<iostream>
#include<stdlib.h>
int main(){
    int i;
        char *p= (char *)malloc(10);
        char *pt=p;
        for(i=0;i<10;i++){
                p[i]='z';
        }
        delete p;
        pt[1]='x';
        free(pt);
    return 0;
}

三 编译运行

[root@localhost charpter05]# ./0513
*** Error in `./0513': double free or corruption (fasttop): 0x00000000015b2010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7c619)[0x7fd177b80619]
./0513[0x400821]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fd177b25c05]
./0513[0x4006f9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:00 67443254                           /root/omc++/charpter05/0513
00600000-00601000 r--p 00000000 fd:00 67443254                           /root/omc++/charpter05/0513
00601000-00602000 rw-p 00001000 fd:00 67443254                           /root/omc++/charpter05/0513
015b2000-015d3000 rw-p 00000000 00:00 0                                  [heap]
7fd170000000-7fd170021000 rw-p 00000000 00:00 0
7fd170021000-7fd174000000 ---p 00000000 00:00 0
7fd177b04000-7fd177cbc000 r-xp 00000000 fd:00 33585750                   /usr/lib64/libc-2.17.so
7fd177cbc000-7fd177ebc000 ---p 001b8000 fd:00 33585750                   /usr/lib64/libc-2.17.so
7fd177ebc000-7fd177ec0000 r--p 001b8000 fd:00 33585750                   /usr/lib64/libc-2.17.so
7fd177ec0000-7fd177ec2000 rw-p 001bc000 fd:00 33585750                   /usr/lib64/libc-2.17.so
7fd177ec2000-7fd177ec7000 rw-p 00000000 00:00 0
7fd177ec7000-7fd177edc000 r-xp 00000000 fd:00 33554691                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7fd177edc000-7fd1780db000 ---p 00015000 fd:00 33554691                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7fd1780db000-7fd1780dc000 r--p 00014000 fd:00 33554691                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7fd1780dc000-7fd1780dd000 rw-p 00015000 fd:00 33554691                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7fd1780dd000-7fd1781de000 r-xp 00000000 fd:00 33585758                   /usr/lib64/libm-2.17.so
7fd1781de000-7fd1783dd000 ---p 00101000 fd:00 33585758                   /usr/lib64/libm-2.17.so
7fd1783dd000-7fd1783de000 r--p 00100000 fd:00 33585758                   /usr/lib64/libm-2.17.so
7fd1783de000-7fd1783df000 rw-p 00101000 fd:00 33585758                   /usr/lib64/libm-2.17.so
7fd1783df000-7fd1784c8000 r-xp 00000000 fd:00 33554693                   /usr/lib64/libstdc++.so.6.0.19
7fd1784c8000-7fd1786c8000 ---p 000e9000 fd:00 33554693                   /usr/lib64/libstdc++.so.6.0.19
7fd1786c8000-7fd1786d0000 r--p 000e9000 fd:00 33554693                   /usr/lib64/libstdc++.so.6.0.19
7fd1786d0000-7fd1786d2000 rw-p 000f1000 fd:00 33554693                   /usr/lib64/libstdc++.so.6.0.19
7fd1786d2000-7fd1786e7000 rw-p 00000000 00:00 0
7fd1786e7000-7fd178708000 r-xp 00000000 fd:00 33585742                   /usr/lib64/ld-2.17.so
7fd1788f9000-7fd1788fe000 rw-p 00000000 00:00 0
7fd178906000-7fd178908000 rw-p 00000000 00:00 0
7fd178908000-7fd178909000 r--p 00021000 fd:00 33585742                   /usr/lib64/ld-2.17.so
7fd178909000-7fd17890a000 rw-p 00022000 fd:00 33585742                   /usr/lib64/ld-2.17.so
7fd17890a000-7fd17890b000 rw-p 00000000 00:00 0
7fffe0f6a000-7fffe0f8b000 rw-p 00000000 00:00 0                          [stack]
7fffe0ffb000-7fffe0ffd000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)

此时程序处于coredump状态。

四 用Valgrind检测内存管理错误

[root@localhost charpter05]# valgrind ./0513
==19563== Memcheck, a memory error detector
==19563== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19563== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==19563== Command: ./0513
==19563==
==19563== Mismatched free() / delete / delete []
==19563==    at 0x4C2B46D: operator delete(void*) (vg_replace_malloc.c:586)
==19563==    by 0x400809: main (0513.cpp:10)
==19563==  Address 0x5a1a040 is 0 bytes inside a block of size 10 alloc'd
==19563==    at 0x4C29EC3: malloc (vg_replace_malloc.c:309)
==19563==    by 0x4007CE: main (0513.cpp:5)
==19563==
==19563== Invalid write of size 1
==19563==    at 0x400812: main (0513.cpp:11)
==19563==  Address 0x5a1a041 is 1 bytes inside a block of size 10 free'd
==19563==    at 0x4C2B46D: operator delete(void*) (vg_replace_malloc.c:586)
==19563==    by 0x400809: main (0513.cpp:10)
==19563==  Block was alloc'd at
==19563==    at 0x4C29EC3: malloc (vg_replace_malloc.c:309)
==19563==    by 0x4007CE: main (0513.cpp:5)
==19563==
==19563== Invalid free() / delete / delete[] / realloc()
==19563==    at 0x4C2AFBD: free (vg_replace_malloc.c:540)
==19563==    by 0x400820: main (0513.cpp:12)
==19563==  Address 0x5a1a040 is 0 bytes inside a block of size 10 free'd
==19563==    at 0x4C2B46D: operator delete(void*) (vg_replace_malloc.c:586)
==19563==    by 0x400809: main (0513.cpp:10)
==19563==  Block was alloc'd at
==19563==    at 0x4C29EC3: malloc (vg_replace_malloc.c:309)
==19563==    by 0x4007CE: main (0513.cpp:5)
==19563==
==19563==
==19563== HEAP SUMMARY:
==19563==     in use at exit: 0 bytes in 0 blocks
==19563==   total heap usage: 1 allocs, 2 frees, 10 bytes allocated
==19563==
==19563== All heap blocks were freed -- no leaks are possible
==19563==
==19563== For lists of detected and suppressed errors, rerun with: -s
==19563== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

五 分析

1 下面输出说明第10行分配和释放函数不一致

==19563== Mismatched free() / delete / delete []
==19563==    at 0x4C2B46D: operator delete(void*) (vg_replace_malloc.c:586)
==19563==    by 0x400809: main (0513.cpp:10)
==19563==  Address 0x5a1a040 is 0 bytes inside a block of size 10 alloc'd
==19563==    at 0x4C29EC3: malloc (vg_replace_malloc.c:309)
==19563==    by 0x4007CE: main (0513.cpp:5)

2 下面输出说明第11行发送非法写错误

==19563== Invalid write of size 1
==19563==    at 0x400812: main (0513.cpp:11)
==19563==  Address 0x5a1a041 is 1 bytes inside a block of size 10 free'd
==19563==    at 0x4C2B46D: operator delete(void*) (vg_replace_malloc.c:586)
==19563==    by 0x400809: main (0513.cpp:10)
==19563==  Block was alloc'd at
==19563==    at 0x4C29EC3: malloc (vg_replace_malloc.c:309)
==19563==    by 0x4007CE: main (0513.cpp:5)

3 下面输出说明第12行释放内存函数无效

==19563== Invalid free() / delete / delete[] / realloc()
==19563==    at 0x4C2AFBD: free (vg_replace_malloc.c:540)
==19563==    by 0x400820: main (0513.cpp:12)
==19563==  Address 0x5a1a040 is 0 bytes inside a block of size 10 free'd
==19563==    at 0x4C2B46D: operator delete(void*) (vg_replace_malloc.c:586)
==19563==    by 0x400809: main (0513.cpp:10)
==19563==  Block was alloc'd at
==19563==    at 0x4C29EC3: malloc (vg_replace_malloc.c:309)
==19563==    by 0x4007CE: main (0513.cpp:5)

4 程序非法读写内存不一定会出现coredump,但释放无效内存则一定会出现coredump.

上一篇:RHEL 8 安装 Oracle 19c 提示缺少 libnsl.so.1


下一篇:yum安装报错 sslv3