Valgrind 内存检测

本文介绍使用Valgrind工具检测六种常见的内存错误案例,包括内存覆盖、内存读写越界、使用未初始化内存、堆内存管理错误、内存泄露等,并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0、安装valgrind

wget http://valgrind.org/downloads/valgrind-3.11.0.tar.bz2
tar xvf valgrind-3.11.0.tar.bz2
cd valgrind-3.11.0/
./configure
make
sudo make install

错误:
==24326== Memcheck, a memory error detector
==24326== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==24326== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==24326== Command: ./sample
==24326==

valgrind: Fatal error at startup: a function redirection
valgrind: which is mandatory for this platform-tool combination
valgrind: cannot be set up. Details of the redirection are:
valgrind:
valgrind: A must-be-redirected function
valgrind: whose name matches the pattern: strlen
valgrind: in an object with soname matching: ld-linux-x86-64.so.2
valgrind: was not found whilst processing
valgrind: symbols from the object with soname: ld-linux-x86-64.so.2
valgrind:
valgrind: Possible fixes: (1, short term): install glibc's debuginfo
valgrind: package on this machine. (2, longer term): ask the packagers
valgrind: for your Linux distribution to please in future ship a non-
valgrind: stripped ld.so (or whatever the dynamic linker .so is called)
valgrind: that exports the above-named function using the standard
valgrind: calling conventions for this platform. The package you need
valgrind: to install for fix (1) is called
valgrind:
valgrind: On Debian, Ubuntu: libc6-dbg
valgrind: On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo
valgrind:
valgrind: Cannot continue -- exiting now. Sorry.

解决办法:
sudo apt-get install libc6-dbg

1、申请的堆内存没有释放 + 对堆内存的访问越界

#include <cstdlib>

void fun() {
    int *p = (int *)malloc(10 * sizeof(int));
    p[10] = 0;
}

int main() {
    fun();
    return 0;
}

g++ -g -O0 sample1.cpp -o sample1
valgrind ./sample1

==25248== Memcheck, a memory error detector
==25248== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25248== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==25248== Command: ./sample1
==25248==
==25248== Invalid write of size 4
==25248== at 0x40054E: fun() (sample.cpp:5)
==25248== by 0x40055E: main (sample.cpp:9)
==25248== Address 0x51fc068 is 0 bytes after a block of size 40 alloc'd
==25248== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==25248== by 0x400541: fun() (sample.cpp:4)
==25248== by 0x40055E: main (sample.cpp:9)
==25248==
==25248==
==25248== HEAP SUMMARY:
==25248== in use at exit: 40 bytes in 1 blocks
==25248== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==25248==
==25248== LEAK SUMMARY:
==25248== definitely lost: 40 bytes in 1 blocks
==25248== indirectly lost: 0 bytes in 0 blocks
==25248== possibly lost: 0 bytes in 0 blocks
==25248== still reachable: 0 bytes in 0 blocks
==25248== suppressed: 0 bytes in 0 blocks
==25248== Rerun with --leak-check=full to see details of leaked memory
==25248==
==25248== For counts of detected and suppressed errors, rerun with: -v
==25248== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

2、使用未初始化的内存

#include <cstdio>

int main() {
    int a[5];
    int i, s;
    a[0] = a[1] = a[3] = a[4] = 0;
    s = 0;
    for(i = 0; i < 5; i++)
        s += a[i];
    if(s == 377)
        printf("sum is %d\n", s);
    return 0;
}

g++ -g -O0 sample2.cpp -o sample2
valgrind ./sample2

==26180== Memcheck, a memory error detector
==26180== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==26180== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==26180== Command: ./sample2
==26180==
==26180== Conditional jump or move depends on uninitialised value(s)
==26180== at 0x40057B: main (sample2.cpp:10)
==26180==
==26180==
==26180== HEAP SUMMARY:
==26180== in use at exit: 0 bytes in 0 blocks
==26180== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==26180==
==26180== All heap blocks were freed -- no leaks are possible
==26180==
==26180== For counts of detected and suppressed errors, rerun with: -v
==26180== Use --track-origins=yes to see where uninitialised values come from
==26180== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

3、内存读写越界

#include <cstdio>
#include <cstdlib>

int main() {
    int len = 4;
    int *pt = (int *)malloc(len * sizeof(int));
    int *p = pt;
    for(int i = 0; i < len; i++)
        p++;
    *p = 4;
    printf("the value of p equal:%d", *p);
    return 0;
}

g++ -g -O0 sample3.cpp -o sample3
valgrind ./sample3

==26686== Memcheck, a memory error detector
==26686== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==26686== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==26686== Command: ./sample3
==26686==
==26686== Invalid write of size 4
==26686== at 0x4005C7: main (sample3.cpp:10)
==26686== Address 0x51fc050 is 0 bytes after a block of size 16 alloc'd
==26686== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==26686== by 0x40059C: main (sample3.cpp:6)
==26686==
==26686== Invalid read of size 4
==26686== at 0x4005D1: main (sample3.cpp:11)
==26686== Address 0x51fc050 is 0 bytes after a block of size 16 alloc'd
==26686== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==26686== by 0x40059C: main (sample3.cpp:6)
==26686==
the value of p equal:4==26686==
==26686== HEAP SUMMARY:
==26686== in use at exit: 16 bytes in 1 blocks
==26686== total heap usage: 1 allocs, 0 frees, 16 bytes allocated
==26686==
==26686== LEAK SUMMARY:
==26686== definitely lost: 16 bytes in 1 blocks
==26686== indirectly lost: 0 bytes in 0 blocks
==26686== possibly lost: 0 bytes in 0 blocks
==26686== still reachable: 0 bytes in 0 blocks
==26686== suppressed: 0 bytes in 0 blocks
==26686== Rerun with --leak-check=full to see details of leaked memory
==26686==
==26686== For counts of detected and suppressed errors, rerun with: -v
==26686== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

4、内存覆盖

#include <cstdio>
#include <cstdlib>
#include <cstring>

int main() {
    char x[50];
    int i;
    for(i = 0; i < 50; i++)
        x[i] = i + 1;
    strncpy(x + 20, x, 20); //ok
    strncpy(x + 20, x, 21); //overlap
    strncpy(x, x + 20, 20); //ok
    strncpy(x, x + 20, 22); //overlap
    x[39] = '\0';
    strcpy(x, x + 20);      //ok
    x[39] = 39;
    x[40] = '\0';
    strcpy(x, x + 20);      //overlap
    return 0;
}

g++ -g -O0 sample4.cpp -o sample4
valgrind ./sample4

==27281== Memcheck, a memory error detector
==27281== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==27281== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==27281== Command: ./sample4
==27281==
==27281== Source and destination overlap in strncpy(0xfff000a09, 0xfff0009f5, 21)
==27281== at 0x4C2E333: __strncpy_sse2_unaligned (vg_replace_strmem.c:548)
==27281== by 0x400660: main (sample4.cpp:11)
==27281==
==27281== Source and destination overlap in strncpy(0xfff0009f6, 0xfff000a0a, 22)
==27281== at 0x4C2E333: __strncpy_sse2_unaligned (vg_replace_strmem.c:548)
==27281== by 0x400698: main (sample4.cpp:13)
==27281==
==27281== Source and destination overlap in strcpy(0xfff0009e0, 0xfff0009f4)
==27281== at 0x4C2DD72: strcpy (vg_replace_strmem.c:506)
==27281== by 0x4006D2: main (sample4.cpp:18)
==27281==
==27281==
==27281== HEAP SUMMARY:
==27281== in use at exit: 0 bytes in 0 blocks
==27281== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==27281==
==27281== All heap blocks were freed -- no leaks are possible
==27281==
==27281== For counts of detected and suppressed errors, rerun with: -v
==27281== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

5、动态内存管理错误

#include <cstdio>
#include <cstdlib>

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

g++ -g -O0 sample5.cpp -o sample5
valgrind ./sample5

==30471== Memcheck, a memory error detector
==30471== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==30471== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==30471== Command: ./sample5
==30471==
==30471== Mismatched free() / delete / delete []
==30471== at 0x4C2C171: operator delete(void) (vg_replace_malloc.c:575)
==30471== by 0x4006E9: main (sample5.cpp:10)
==30471== Address 0x5a1c040 is 0 bytes inside a block of size 10 alloc'd
==30471== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==30471== by 0x4006AE: main (sample5.cpp:6)
==30471==
==30471== Invalid write of size 1
==30471== at 0x4006F2: main (sample5.cpp:11)
==30471== Address 0x5a1c041 is 1 bytes inside a block of size 10 free'd
==30471== at 0x4C2C171: operator delete(void
) (vg_replace_malloc.c:575)
==30471== by 0x4006E9: main (sample5.cpp:10)
==30471== Block was alloc'd at
==30471== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==30471== by 0x4006AE: main (sample5.cpp:6)
==30471==
==30471== Invalid free() / delete / delete[] / realloc()
==30471== at 0x4C2BD57: free (vg_replace_malloc.c:530)
==30471== by 0x400700: main (sample5.cpp:12)
==30471== Address 0x5a1c040 is 0 bytes inside a block of size 10 free'd
==30471== at 0x4C2C171: operator delete(void*) (vg_replace_malloc.c:575)
==30471== by 0x4006E9: main (sample5.cpp:10)
==30471== Block was alloc'd at
==30471== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
==30471== by 0x4006AE: main (sample5.cpp:6)
==30471==
==30471==
==30471== HEAP SUMMARY:
==30471== in use at exit: 0 bytes in 0 blocks
==30471== total heap usage: 1 allocs, 2 frees, 10 bytes allocated
==30471==
==30471== All heap blocks were freed -- no leaks are possible
==30471==
==30471== For counts of detected and suppressed errors, rerun with: -v
==30471== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

6、内存泄露

#include <cstdio>
#include <cstdlib>

typedef struct _node {
    struct _node *l;
    struct _node *r;
    char v;
}node;

node *mk(node *l, node *r, char val) {
    node *f = (node *)malloc(sizeof(*f));
    f->l = l;
    f->r = r;
    f->v = val;
    return f;
}

void nodefr(node *n) {
    if(n) {
        nodefr(n->l);
        nodefr(n->r);
        free(n);
    }
}

int main() {
    node *tree1, *tree2, *tree3;
    tree1 = mk(mk(mk(0, 0, '3'), 0, '2'), 0, '1');
    tree2 = mk(0, mk(0, mk(0, 0, '6'), '5'), '4');
    tree3 = mk(mk(tree1, tree2, '8'), 0, '7');
    return 0;
}

g++ -g -O0 sample6.cpp -o sample6
valgrind ./sample6

==31147== Memcheck, a memory error detector
==31147== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==31147== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==31147== Command: ./sample6
==31147==
==31147==
==31147== HEAP SUMMARY:
==31147== in use at exit: 192 bytes in 8 blocks
==31147== total heap usage: 8 allocs, 0 frees, 192 bytes allocated
==31147==
==31147== LEAK SUMMARY:
==31147== definitely lost: 24 bytes in 1 blocks
==31147== indirectly lost: 168 bytes in 7 blocks
==31147== possibly lost: 0 bytes in 0 blocks
==31147== still reachable: 0 bytes in 0 blocks
==31147== suppressed: 0 bytes in 0 blocks
==31147== Rerun with --leak-check=full to see details of leaked memory
==31147==
==31147== For counts of detected and suppressed errors, rerun with: -v
==31147== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值