Detected memory leaks!内存泄漏,溢出,内存越界问题分析
2016-07-22 09:48
525 查看
应用程序发生 Detected memory leaks!内存泄漏 一直程序员面对的是一个很痛苦的问题,要查出泄漏的地方有时候需要大半天甚至更长时间。这里讲讲我的一些查找内存泄漏以及避免内存泄漏的一些经验
1.数组相关
#define ITEM_COUNT 30
WORD m_arrRreset[ITEM_COUNT] = {0};
for (int i = 0 i < ITEM_COUNT; i++)
{
m_arrRreset[i] =i*6;
}
memcpy(m_arrRreset, m_arrRresetReq,sizeof(WORD)*FM_AM_PRESET_COUNT);
注意数组大小最好用const类型或宏定义,这样for循环遍历时,就不容易出现数组越界,内存操作函数中数据的大小也不要用具体数字(如 30)表示,避免造成混乱
2..指针相关
a.局部变量new了内存,用完了,就一定立马在函数内delete释放掉
#define
BUFF_SIZE 256
void parsedata(char* lpCmd)
{
int nCmdLen = strlen(lpCmd);
BYTE pTempBuffer[BUFF_SIZE ] = {0};
BYTE *lpCurrentCmd = pTempBuffer;
if (nCmdLen > sizeof(pTempBuffer))
{
lpCurrentCmd = new BYTE[nCmdLen];
}
memcpy(lpCurrentCmd, lpCmd, nCmdLen);
....................................
....................................
//这里使用了一个技巧
//为了避免总是new内存,在数组能完全满足要求的情况下,直接用数组内存。非常高效完美的技巧。
if (lpCurrentCmd != pTempBuffer)
{
delete[] lpCurrentCmd;
lpCurrentCmd = NULL;
}
}
b. 指针作为返回值,在函数内部分配了内存(ps:局部的数组是不能作为函数返回值的,函数返回,内存就释放了,一定要用new的堆内存或静态变量),此种情况最容易,忘记释放内存。
char *getFullDstFilePath(char *strDirPath, char *strFileName)
{
char *fullName = NULL;
if ((fullName = (char *)malloc(strlen(strDirPath) + strlen(strFileName) )) == NULL)
{
memset(fullName, 0, strlen(fullName));
perror("Malloc fullName err");
}else
{
if (strDirPath[strlen(strDirPath) -1] == '/')
{
strcpy(fullName, strDirPath);
strcat(fullName, strFileName);
}else
{
strcpy(fullName, strDirPath);
strcat(fullName, "/");
strcat(fullName, strFileName);
}
}
return fullName; //返回堆内存,需要在函数外释放
}
函数调用
char *fullDstFilePath = NULL;
fullDstFilePath = getFullDstFilePath(strSrcDir, tdirname->d_name);
//虽然看不是fullDstFilePath分配了内存,但它指向的是malloc出来的堆内存,用完了,一定要释放
//if(fullDstFilePath!= NULL)
{
free(fullDstFilePath);
fullDstFilePath = NULL;
}
说明下free delete一个为NULL的指针,不会产生错误。大家可以自己尝试下。但文件close两次会产生错误
c。指针是函数形参的情况,需要传变量的地址进去
一般函数内部会检查此形参指针指向的是否是NULL内存。
int nCmdLen = 0;
BYTE* lpCmd = fpGetCmdBuf( hFp, &nCmdLen);
记得lpCmd
需要释放 见上面的情况 b. 指针作为返回值
函数原型
//lpCmdLen, [out], 返回该命令的长度,不能为NULL
BYTE* fpGetCmdBuf(HANDLE hFp, int* lpCmdLen);
d。 成员变量的释放,比较好解决,程序退出前,判断下是否指向的内存是NULL,不是就释放。
CInfo::~CInfo(void)
{
if ( m_pMap != NULL)
{
delete m_pMap;
m_pMap = NULL;
}
} //析构函数释放,就可以了
e。其他文件,句柄的释放,如文件,HANDLE,Socket的关闭同理。
本质上HANDLE就是指针
typedef void *HANDLE;
java有个try cache finilly 规范操作都是在finilly里面关闭文件,Socket。
使用动态内存分配的程序中,常见错误。
1. 对NULL指针进行解引用操作 ,忘记检查所请求的内存是否成功分配。
2. 对分配的内存进行操作时越过边界
3. 释放并非动态分配的内存
4. 试图释放一块动态分配的内存的一部分以及一块内存被释放之后被继续使用。释放一块内存的一部分是不允许的。动态分配的内存必须整块一起释放
1.数组相关
#define ITEM_COUNT 30
WORD m_arrRreset[ITEM_COUNT] = {0};
for (int i = 0 i < ITEM_COUNT; i++)
{
m_arrRreset[i] =i*6;
}
memcpy(m_arrRreset, m_arrRresetReq,sizeof(WORD)*FM_AM_PRESET_COUNT);
注意数组大小最好用const类型或宏定义,这样for循环遍历时,就不容易出现数组越界,内存操作函数中数据的大小也不要用具体数字(如 30)表示,避免造成混乱
2..指针相关
a.局部变量new了内存,用完了,就一定立马在函数内delete释放掉
#define
BUFF_SIZE 256
void parsedata(char* lpCmd)
{
int nCmdLen = strlen(lpCmd);
BYTE pTempBuffer[BUFF_SIZE ] = {0};
BYTE *lpCurrentCmd = pTempBuffer;
if (nCmdLen > sizeof(pTempBuffer))
{
lpCurrentCmd = new BYTE[nCmdLen];
}
memcpy(lpCurrentCmd, lpCmd, nCmdLen);
....................................
....................................
//这里使用了一个技巧
//为了避免总是new内存,在数组能完全满足要求的情况下,直接用数组内存。非常高效完美的技巧。
if (lpCurrentCmd != pTempBuffer)
{
delete[] lpCurrentCmd;
lpCurrentCmd = NULL;
}
}
b. 指针作为返回值,在函数内部分配了内存(ps:局部的数组是不能作为函数返回值的,函数返回,内存就释放了,一定要用new的堆内存或静态变量),此种情况最容易,忘记释放内存。
char *getFullDstFilePath(char *strDirPath, char *strFileName)
{
char *fullName = NULL;
if ((fullName = (char *)malloc(strlen(strDirPath) + strlen(strFileName) )) == NULL)
{
memset(fullName, 0, strlen(fullName));
perror("Malloc fullName err");
}else
{
if (strDirPath[strlen(strDirPath) -1] == '/')
{
strcpy(fullName, strDirPath);
strcat(fullName, strFileName);
}else
{
strcpy(fullName, strDirPath);
strcat(fullName, "/");
strcat(fullName, strFileName);
}
}
return fullName; //返回堆内存,需要在函数外释放
}
函数调用
char *fullDstFilePath = NULL;
fullDstFilePath = getFullDstFilePath(strSrcDir, tdirname->d_name);
//虽然看不是fullDstFilePath分配了内存,但它指向的是malloc出来的堆内存,用完了,一定要释放
//if(fullDstFilePath!= NULL)
{
free(fullDstFilePath);
fullDstFilePath = NULL;
}
说明下free delete一个为NULL的指针,不会产生错误。大家可以自己尝试下。但文件close两次会产生错误
c。指针是函数形参的情况,需要传变量的地址进去
一般函数内部会检查此形参指针指向的是否是NULL内存。
int nCmdLen = 0;
BYTE* lpCmd = fpGetCmdBuf( hFp, &nCmdLen);
记得lpCmd
需要释放 见上面的情况 b. 指针作为返回值
函数原型
//lpCmdLen, [out], 返回该命令的长度,不能为NULL
BYTE* fpGetCmdBuf(HANDLE hFp, int* lpCmdLen);
d。 成员变量的释放,比较好解决,程序退出前,判断下是否指向的内存是NULL,不是就释放。
CInfo::~CInfo(void)
{
if ( m_pMap != NULL)
{
delete m_pMap;
m_pMap = NULL;
}
} //析构函数释放,就可以了
e。其他文件,句柄的释放,如文件,HANDLE,Socket的关闭同理。
本质上HANDLE就是指针
typedef void *HANDLE;
java有个try cache finilly 规范操作都是在finilly里面关闭文件,Socket。
使用动态内存分配的程序中,常见错误。
1. 对NULL指针进行解引用操作 ,忘记检查所请求的内存是否成功分配。
2. 对分配的内存进行操作时越过边界
3. 释放并非动态分配的内存
4. 试图释放一块动态分配的内存的一部分以及一块内存被释放之后被继续使用。释放一块内存的一部分是不允许的。动态分配的内存必须整块一起释放
相关文章推荐
- 关于指针的一些事情
- IE7降低内存和降低CPU的几个技巧
- 如何高效的使用内存
- DOS下内存的配置
- XP/win2003下发现1G的内存比512M还慢的解决方法
- PowerShell实现动态获取当前脚本运行时消耗的内存
- C#实现把dgv里的数据完整的复制到一张内存表的方法
- SQL语句实现查询SQL Server内存使用状况
- C# Pointer指针应用实例简述
- C和指针小结(推荐)
- C语言内存对齐实例详解
- C++智能指针实例详解
- 浅谈C++指针(必看)
- c语言内存泄露示例解析
- 深入学习C语言中memset()函数的用法
- C++指向函数的指针实例解析
- 关于c语言指针的两处小tip分享
- 浅谈c/c++中使用指针需要注意的问题
- 浅析iterator与指针的区别
- 探讨C++中数组名与指针的用法比较分析