C 内存泄漏检测 Demo

思路:通过宏,将 malloc 进行替换,并封装成自己的malloc
在自己的 malloc 中在用户申请的内存基础上多出一个自己管理的结构体,位于最前面。并管理一个链表。
释放时通过偏移量获取结构体,然后从链表中删除。

memdebug.c

#include <stdio.h>
#include <stdlib.h>

typedef struct memdebug
{
    void *p;
    size_t size;
    int line;
    const char *file;
    struct memdebug *next;
    struct memdebug *prev;
} memdebug_t;

static memdebug_t *head;

void *memdebug_alloc(size_t size, const char *file, int line)
{
    memdebug_t *mem = (memdebug_t *)malloc(size + sizeof(memdebug_t));
    if (mem == NULL)
        return NULL;

    mem->p = mem + 1;
    mem->size = size;
    mem->file = file;
    mem->line = line;
    mem->next = mem->prev = NULL;

    // printf("malloc: %d %s:%d\n", size, file, line);

    if (head == NULL)
        head = mem;
    else
    {
        if (head->prev)
        {
            head->prev->next = mem;
            mem->prev = head->prev;
        }
        head->prev = mem;
        mem->next = head;
        head = mem;
    }

    return mem->p;
}

void memdebug_free(void *p, const char *file, int line)
{
    if (p == NULL)
        return;

    memdebug_t *mem = (memdebug_t *)(p - sizeof(memdebug_t));
    if (mem->p != p)
        return;

    // printf("free: %d %s:%d, malloc in %s:%d\n", mem->size, file, line, mem->file, mem->line);

    if (head == mem && head->next == NULL)
        head = NULL;
    else if (head == mem)
    {
        head->next->prev = NULL;
        head = head->next;
    }
    else
    {
        if (mem->prev)
            mem->prev->next = mem->next;
        if (mem->next)
            mem->next->prev = mem->prev;
    }

    mem->p = NULL;
    free(mem);
}

void memdebug_print(void)
{
    for (memdebug_t *mem = head; mem; mem = mem->next)
        printf("mem: %d %s:%d\n", mem->size, mem->file, mem->line);
}

memdebug.h

#ifndef __MEMDEBUG_H__
#define __MEMDEBUG_H__
#include <stdint.h>

void *memdebug_alloc(size_t size, const char *file, int line);
void memdebug_free(void *p, const char *file, int line);
void memdebug_print(void);

#define malloc(size) memdebug_alloc(size, __FILE__, __LINE__)
#define free(p) memdebug_free(p, __FILE__, __LINE__)

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include "memdebug.h"

void test(void)
{
    char *s;
    for (int i = 0; i < 10; i++)
    {
        s = (char*)malloc(i*10);
        if(i % 2 == 0)
            free(s);
    }

    char buf[1011];
    free(buf);
    free(s);
    free(s);
}

int main(int argc, char const *argv[])
{
    test();
    memdebug_print();

    return 0;
}

当需要调试时只需在 #include <stdlib.h> 前加入 #include “memdebug.h”,不影响原始代码。

memdebug_print 打印出来的就是未释放的内存信息,这些内存当然包括运行时常驻内存,当然也包括泄漏的内存。

当程序出错时,可以打印出来,然后手动检测每一个没有释放的那些内存。

到这里就只能手动了,是的,这个还没有强大到自动识别泄漏的内存,主要是你无法知道有哪些内存申请了,但是引用丢失了。C++智能指针似乎可以做到。虽然可以实现类似引用计数,但在写代码时会增加很多约束,实现起来似乎也比较麻烦。

这个就适合代码量不大的内存泄漏,但是代码量不大,还担心屁的内存泄漏。所以没什么用的东西。

代码量大的话,有上千个内存申请,一个一个排查,还是挺费时的。但总比原始的方式从源代码中排除好很多。

它能够统计同一行内存申请代码行被调用了多少次,而这部分很可能就是泄漏源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值