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;
}