Linux C程序内存泄露检测

对于程序员来说,最痛苦的就是内存的申请与释放。内存泄露也是程序中经常遇到的问题。为了更好的定位内存泄露问题,我们有必要熟悉一些内存泄露的检测工具。今天主要找到了以下四个内存检测工具,使用起来都比较方便。

valgrind

安装valgrind,执行下列程序

#include <stdlib.h>

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

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

编译:
gcc -g -o valgrindtst valgrindtst.c

执行内存检测:

valgrind –tool=memcheck -leak-check=full ./valgrindtst

内存检测结果:

==19896== Memcheck, a memory error detector
==19896== Copyright (C) 2002-2013, and GNU GPL’d, by Julian Seward et al.
==19896== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==19896== Command: ./valgrindtst
==19896==
==19896== Invalid write of size 4
==19896== at 0x80483DF: func (valgrindtst.c:6)
==19896== by 0x80483F1: main (valgrindtst.c:11)
==19896== Address 0x401a050 is 0 bytes after a block of size 40 alloc’d
==19896== at 0x40072D5: malloc (vg_replace_malloc.c:291)
==19896== by 0x80483D5: func (valgrindtst.c:5)
==19896== by 0x80483F1: main (valgrindtst.c:11)
==19896==
==19896==
==19896== HEAP SUMMARY:
==19896== in use at exit: 40 bytes in 1 blocks
==19896== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==19896==
==19896== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==19896== at 0x40072D5: malloc (vg_replace_malloc.c:291)
==19896== by 0x80483D5: func (valgrindtst.c:5)
==19896== by 0x80483F1: main (valgrindtst.c:11)
==19896==
==19896== LEAK SUMMARY:
==19896== definitely lost: 40 bytes in 1 blocks
==19896== indirectly lost: 0 bytes in 0 blocks
==19896== possibly lost: 0 bytes in 0 blocks
==19896== still reachable: 0 bytes in 0 blocks
==19896== suppressed: 0 bytes in 0 blocks
==19896==
==19896== For counts of detected and suppressed errors, rerun with: -v
==19896== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 12 from 8)

检测到内存泄露与数组越界的错误
mtrace

libc提供的内存检测工具。一般系统中都自带该工具。

#include <stdlib.h>
#include <mcheck.h>

void func()
{
    int *p = (int*)malloc(100*sizeof(int));
}

int main()
{
    setenv("MALLOC_TRACE", "logfile",1);
    mtrace();
    func();
    return 0;
}

编译:gcc -g -o mtracetst mtracetst.c
执行程序后,生成logfile文件,内容如下:

= Start
@ ./mtracetst:[0x8048436] + 0x8a35428 0x190
@ /lib/libc.so.6:(clearenv+0x7c)[0x26a87c] - 0x8a35008
@ /lib/libc.so.6:(tdestroy+0x47)[0x318747] - 0x8a35080
@ /lib/libc.so.6:(tdestroy+0x4f)[0x31874f] - 0x8a350a0

内容不太好理解,使用perl语言实现的bin程序mtrace可以将这些内容转换为可读内容,如下:

[root@localhost test]# mtrace logfile
$* is no longer supported at /usr/bin/mtrace line 2.
- 0x0000000008a35008 Free 3 was never alloc’d 0x26a87c
- 0x0000000008a35080 Free 4 was never alloc’d 0x318747
- 0x0000000008a350a0 Free 5 was never alloc’d 0x31874f

Memory not freed:

Address Size Caller
0x0000000008a35428 0x190 at 0x8048436

memwatch

A memory leak detection tool. Basically, you add a header file to your souce code files, and compile with MEMWATCH defined or not. The header file MEMWATCH.H contains detailed instructions. This is a list of some of the features present in version 2.71:
- ANSI C
- Logging to file or user function using TRACE() macro
- Fault tolerant, can repair it’s own data structures
- Detects double-frees and erroneous free’s
- Detects unfreed memory
- Detects overflow and underflow to memory buffers
- Can set maximum allowed memory to allocate, to stress-test app
- ASSERT(expr) and VERIFY(expr) macros
- Can detect wild pointer writes
- Support for OS specific address validation to avoid GP’s (segmentation faults)
- Collects allocation statistics on application, module or line level
- Rudimentary support for threads (see FAQ for details)
- Rudimentary support for C++ (disabled by default, use with care!)

下载,解压,在解压目录中,写如下测试程序:

#include <stdlib.h>
#include "memwatch.h"

int main()
{
    char *p1 = NULL, *p2 = NULL;
    p1 = malloc(100*sizeof(char));
    p2 = malloc(1000*sizeof(char));
    free(p2);
}

编译: gcc -g -o memwatchtst -DMEMWATCH -DMEMWATCH_STDIO memwatchtst.c memwatch.c
执行结果:
[root@localhost memwatch-2.71]# ./memwatchtst
MEMWATCH detected 1 anomalies

在当前目录下生成memwatch.log文件,打开,内容如下:

============= MEMWATCH 2.71 Copyright (C) 1992-1999 Johan Lindh =============

Started at Wed Jan 15 01:30:01 2014

Modes: STDC 64-bit mwDWORD==(unsigned long)
mwROUNDALLOC==8 sizeof(mwData)==32 mwDataSize==32

Stopped at Wed Jan 15 01:30:01 2014

unfreed: <1> memwatchtst.c(7), 100 bytes at 0x9ea11f0 {FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE …………….}

Memory usage statistics (global):
N)umber of allocations made: 2
L)argest memory usage : 1100
T)otal of all alloc() calls: 1100
U)nfreed bytes totals : 100

gc

垃圾回收器、内存泄露检测

安装gc,然后可以执行下列测试程序

#include <gc.h>
#include <stdio.h>
#include <stdlib.h>
#include <gc/leak_detector.h>
void test()
{
    int i;
    char *p;
    for(i=0; i < 10000; i++)
    {
         p = GC_malloc(100000*sizeof(int));
         if(NULL == p)
         {
             printf("NO memory\n");
             break;
          }
     }

}

void chkmem()
{
    int *p[10];
    int i;
    GC_find_leak = 1;
    for(i=0; i < 10; i++)
    {
         p[i] = (int *)malloc(sizeof(int)+i);
    }
    for(i=0; i<7;i++)
    {
         free(p[i]);
    }
    for(i=3; i < 10; i++)
    {
         p[i] = (int *)malloc(sizeof(int)+i);
    }
    CHECK_LEAKS();
}
int main()
{
    test();
    chkmem();
}

编译:

export export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

gcc -g -o gctst gctst.c -lgc

执行结果:

[root@localhost test]# ./gctst
Leaked composite object at start: 0x93d2000, appr. length: 400008
Leaked composite object at start: 0x93b2fa0, appr. length: 16
Leaked composite object at start: 0x93b2fb0, appr. length: 16
Leaked composite object at start: 0x93b2fc0, appr. length: 16
Leaked composite object at start: 0x94f8000, appr. length: 400008
Leaked composite object at start: 0x9496000, appr. length: 400008
Leaked composite object at start: 0x9434000, appr. length: 400008

注:test函数说明gc有自动回收内存的机制;chkmem函数说明,gc可以检测内存泄露

valgrind和memwatch的输出信息比较适合我们的阅读习惯,可以很容易定位内存泄露的位置。gc有垃圾内存回收机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值