您的位置:首页 > 编程语言 > C语言/C++

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. 试图释放一块动态分配的内存的一部分以及一块内存被释放之后被继续使用。释放一块内存的一部分是不允许的。动态分配的内存必须整块一起释放

     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息