检测内存泄漏malloc模块

1)实际应用中,很多地方用到malloc动态申请内存,其实频繁使用应该没有什么碎片之类的影响,linux会帮我们优化,只要我们使用后正常free就ok了。

2)检测思路是每次malloc申请的时候记录一下此时申请的位置(函数名,行号),在/tmp/下建立以位置等信息命名的空文件。free时候再把相应的文件删除掉。

3)这里用到一个小技巧,每次malloc的时候多申请一点内存,用作记录内存信息头。

4)把对应的一些宏写成空宏即可。

#ifndef __COMMON_H__
#define __COMMON_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>

#define HEAP_TEST

#ifdef HEAP_TEST
#define COMMON_Malloc(size) COMMON_Malloc1(size, __FUNCTION__, __LINE__)
#define COMMON_Free(ptr) COMMON_Free1(ptr)
#else
#define COMMON_Malloc(size) malloc(size)
#define COMMON_Free(ptr) free(ptr)
#endif

void* COMMON_Malloc1(int bytes, const char* func, int line);
int COMMON_Free1(void* ptr);
int COMMON_GetMallocSum();
int COMMON_MonotonicTime(struct timeval* pTime);
int COMMON_GetRealTime(struct timeval* pTime);
int COMMON_IntervalTime(struct timeval* pStart, struct timeval* pEnd); // return interval time (ms)

#ifdef __cplusplus
}
#endif

#endif
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "common.h"
#include "debug.h"

static unsigned int malloc_sum = 0;

typedef struct MEM_HEAD_S
{
    void* this;
    const char* func;
    int line;
    int size;
}MEM_HEAD_S;

static int  COMMON_Align(int bytes)
{
    int ret = 0;
    if (bytes % 4 != 0)
    {
        ret = (bytes/4 + 1) * 4;
    }
    else
    {
        ret = bytes;
    }
    return ret;
}

static void COMMON_CreateOrRmFile(MEM_HEAD_S* pMem, int IsMalloc)
{
    char path[64];
    snprintf(path, sizeof(path), "/tmp/heap_%p_%s_%d_%d", pMem->this, pMem->func, pMem->line, pMem->size);
    if (IsMalloc)
    {
        creat(path, S_IWRITE|S_IREAD|S_IEXEC);
    }
    else
    {
        remove(path);
    }
}

void* COMMON_Malloc1(int bytes, const char* func, int line)
{
    CHECK(bytes > 0, NULL, "invalid parameter.\n");

    bytes += sizeof(MEM_HEAD_S);
    int AlignSize = COMMON_Align(bytes);
    MEM_HEAD_S* ret = (MEM_HEAD_S*)malloc(AlignSize);
    if (NULL != ret)
    {
        ret->this = ret;
        ret->func = func;
        ret->line = line;
        ret->size = AlignSize;
        COMMON_CreateOrRmFile(ret, 1);
        malloc_sum += ret->size;
        ret += 1;
        //DBG("malloc %d ok, total malloc %d\n", AlignSize, malloc_sum);
    }
    else
    {
        ERR("malloc error.size: %d\n", AlignSize);
    }

    return (void*)ret;
}

int COMMON_Free1(void* ptr)
{
    CHECK(NULL != ptr, -1, "invalid parameter.\n");

    MEM_HEAD_S* tmp = (MEM_HEAD_S*)ptr;
    tmp -= 1;
    COMMON_CreateOrRmFile(tmp, 0);
    malloc_sum -= tmp->size;
    //DBG("free %d ok, total malloc %d\n", *tmp, malloc_sum);
    free(tmp);

    return 0;
}

int COMMON_GetMallocSum()
{
    return malloc_sum;
}

static int COMMON_clock_gettime(clockid_t clk_id, struct timeval* pTime)
{
    struct timespec stTime;
    memset(&stTime, 0, sizeof(struct timespec));
    memset(pTime, 0, sizeof(struct timeval));
    if (-1 == clock_gettime(clk_id, &stTime))
    {
        ERR("get clock time failed.\n");
        return -1;
    }
    pTime->tv_sec = stTime.tv_sec;
    pTime->tv_usec = stTime.tv_nsec/1000;

    return 0;
}

int COMMON_MonotonicTime(struct timeval* pTime)
{
    CHECK(NULL != pTime, -1, "invalid parameter.\n");

    return COMMON_clock_gettime(CLOCK_MONOTONIC, pTime);
}

int COMMON_GetRealTime(struct timeval* pTime)
{
    CHECK(NULL != pTime, -1, "invalid parameter.\n");

    return COMMON_clock_gettime(CLOCK_REALTIME, pTime);
}

//单位毫秒
int COMMON_IntervalTime(struct timeval* pStart, struct timeval* pEnd)
{
    CHECK(NULL != pStart, -1, "invalid parameter.\n");

    int IntervalTime = (pEnd->tv_sec -pStart->tv_sec)*1000 + (pEnd->tv_usec - pStart->tv_usec)/1000;

    return IntervalTime;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值