C 如何检测内存出错
来源:互联网 发布:宁波每日新房成交数据 编辑:程序博客网 时间:2024/05/29 09:00
#include "stdio.h"
/**********************************************/
// 关于动态内存检测原理
// (1)检测内存越界方法,在动态申请内存的末端加上特定的标识,当释放的时候,看特定的标识有没有被改变,如果变了,就越界了
// (2)检测内存没有释放方法, 1)重复申请,导致前面申请的内存没有释放,2)遗忘式的内存未释放, 都看日志
//
//
//
//
//
/**********************************************/
#define MAX_NODE_COUNT 1024
#define LOG printf
#define malloc_ext malloc
#define free_ext free
#define zkp_malloc(pptr, size) zkp_malloc_ext(pptr, size, __FILE__, __LINE__)
#define zkp_free(pptr) zkp_free_ext(pptr, __FILE__, __LINE__)
// 关于每次动态申请内存的数据
typedef struct CDown
{
char *m_point; // 记录动态申请的指针
int m_size; // 记录动态申请的内存大小
char m_file[256]; // 记录动态申请的文件
int m_line; // 记录动态申请的行数
}CDown;
typedef struct Cnode
{
CDown m_param[MAX_NODE_COUNT];
int m_count;
}Cnode;
Cnode gDownList;
const int END_FLAG = 0x1234ABCD;
// 检测是否重复申请 ,1表示是多次
int check_multi_alloc(char *p, char *file, int line)
{
int i = 0;
for (; i < gDownList.m_count; i++)
{
if (gDownList.m_param[i].m_point == p)
{
LOG("同一指针出现多次申请内存 %s/t/tLine:%d/r/n", file, line);
return 1;
}
}
return 0;
}
// 把新节点加入到列表, 正常返回值,非负数,添加到第几个节点。负数表示添加到列表失败
int AddNode(CDown *node)
{
int i = 0;
for (;i < MAX_NODE_COUNT; i++)
{
if (NULL == gDownList.m_param[i].m_point)
{
memcpy((void *)(&gDownList.m_param[i]), (void *)node, sizeof(CDown));
++gDownList.m_count;
return i;
}
}
return -1;
}
// 删除节点, 正常返回值,非负数,添加到第几个节点。负数表示添加到列表失败
int DelNode(char *point)
{
int i = 0;
for (;i < MAX_NODE_COUNT; i++)
{
if (point == gDownList.m_param[i].m_point)
{
free_ext(point);
//point = NULL;
memset((void *)&gDownList.m_param[i], 0, sizeof(CDown));
--gDownList.m_count;
return i;
}
}
return -1;
}
//打印出现存的内存信息
int PrintMemoryInfo(void)
{
int i = 0;
LOG("目前还有%d块内存没有释放/r/n", gDownList.m_count);
for (;i < MAX_NODE_COUNT; i++)
{
if (NULL != gDownList.m_param[i].m_point)
{
LOG("未释放内存%s/t/tLINE:%d/t/tsize:%d/r/n", gDownList.m_param[i].m_file, gDownList.m_param[i].m_line, gDownList.m_param[i].m_size);
if (*((int*)gDownList.m_param[i].m_point) != END_FLAG)
{
LOG("越界内存%s/t/tLINE:%d/t/tsize:%d/r/n", gDownList.m_param[i].m_file, gDownList.m_param[i].m_line, gDownList.m_param[i].m_size);
}
}
}
return 1;
}
//打印出出错内存块信息
int PrintErrorMemory(void)
{
int i = 0;
int count = 0;
for (; i < MAX_NODE_COUNT; i++)
{
if ((NULL != gDownList.m_param[i].m_point) && *((int*)(gDownList.m_param[i].m_point + gDownList.m_param[i].m_size)) != END_FLAG)
{
LOG("越界内存%s/t/tLINE:%d/t/tsize:%d/r/n", gDownList.m_param[i].m_file, gDownList.m_param[i].m_line, gDownList.m_param[i].m_size);
count++;
}
}
return 1;
}
//
short zkp_malloc_ext(char **pptr, unsigned int size, char *file, int line)
{
if (NULL != *pptr)
{
LOG("Warning 指针未初始化%s/t/tLine:%d/r/n", file, line);
check_multi_alloc(*pptr, file, line);
}
if (NULL != (*pptr = (char*)malloc_ext(size + sizeof(END_FLAG))))
{
CDown newnode = {0};
newnode.m_point = *pptr;
newnode.m_size = size;
strcpy(newnode.m_file, file);
newnode.m_line = line;
memset((void*)*pptr, 0 , size);
//在内存的末尾加一个标志
memcpy((void *)(*pptr + size), &END_FLAG, sizeof(END_FLAG));
//把新的节点加入到列表中去
AddNode(&newnode);
return 1;
}
return 0;
}
/*
*pptr, 这里传的二级指针
*/
void zkp_free_ext(char **pptr, char *file, int line)
{
if (NULL != *pptr)
{
if (DelNode(*pptr) < 0)
{
LOG("DelNode Error, %s/t/t%d/r/n", file, line);
}
*pptr = NULL;
}
else
{
LOG("Warning -> Error 指针可能被多次释放%s Line:%d/r/n", file, line);
}
PrintErrorMemory();
}
void main(void)
{
char *p = NULL;
zkp_malloc(&p, 40);
zkp_malloc(&p, 40);
memset((void *)p, 0, 50);
PrintMemoryInfo();
}
- C 如何检测内存出错
- 如何检测C/C++程序内存泄露
- C语言中的内存泄露,如何避免,如何检测
- JNI程序如何检测C代码的内存泄漏
- 如何检测C语言中的内存漏洞(leak)?
- 如何使用工具进行C/C++的内存泄漏检测
- 如何检测内存泄漏
- 如何检测内存泄漏
- 如何检测内存泄漏
- 如何检测内存泄漏
- 如何检测内存泄漏
- 如何检测内存泄漏
- 如何检测内存泄露?
- 如何检测内存泄露
- 如何检测内存泄漏
- 如何检测内存泄露
- C 检测内存泄露
- C语言内存检测
- Fedora 14安装VMware Tools过程
- js遮罩层
- js遮罩层
- Windows CE虚拟内存
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- C 如何检测内存出错
- GCC-3.4.6源代码学习笔记(172)
- 孩子为什么不听话?因为你不会批评!
- sqlserver 数据转换 asp.net
- STM32 GPIO
- Studying note of GCC-3.4.6 source (172)
- 资源函数
- SCU 2011 warmup contest 5
- 摘抄一些函数