今天在涉及内存操作的代码中发现了两个如下错误:
看下报错内容:_BLOCK_TYE_IS_VALID(pHead->nBlockUse);
在看下operator delete的定义,定位到报错的地方:
delete运算符
/***
*void operator delete() - delete a block in the debug heap
*
*Purpose:
* Deletes any type of block.
*
*Entry:
* void *pUserData - pointer to a (user portion) of memory block in the
* debug heap
*
*Return:
* <void>
*
*******************************************************************************/
void operator delete(
void *pUserData
)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK); /* block other threads */
__TRY
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
/********************导致报错的断言*******************/
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );
__FINALLY
_munlock(_HEAP_LOCK); /* release other threads */
__END_TRY_FINALLY
return;
}
#endif /* _DEBUG */
在断言处判断内存块释放合法时,出现问题。说明指针指向的内存块IS NOT VALID.
第一个问题的原因是:指针指向的空间已经被释放了,重复释放,会出问题。
看了一下代码,逻辑是这样的:
qMsg.pMsgBody = new char[nDataLen];
memset(qMsg.pMsgBody, 0, nDataLen);
memcpy(qMsg.pMsgBody, pSendDataBuf, nDataLen);
m_pQCon->InsertQMsg(m_strDestQueueName, qMsg);
if (qMsg.pMsgBody)
{
delete qMsg.pMsgBody;
}
在函数InsertQMsg中也有类似的一段代码:
if (qMsg.pMsgBody)
{
delete qMsg.pMsgBody;
}
现在看到了,内存重复释放了。
所以在释放完指针指向的空间时,最好让qMsg.pMsgBody = NULL;这样即使重复释放,通过判断指针是否为NULL,避免重复释放。
这样,就不会重复释放了。
第二个问题,报同样的错,但是产生的原因是不一样的。
在程序中有如下代码:
构造函数:
StreamCachePool::StreamCachePool(int nPoolSize)
{
m_pEntries = new StreamEntity[nPoolSize];
m_nEntCount = 0;
m_nPoolSize = nPoolSize;
}
析构函数:
//关闭流池中所有的文件流,并释放流池空间
StreamCachePool::~StreamCachePool(void)
{
if (m_pEntries) delete m_pEntries;
m_pEntries = NULL;
}
此处StreamEntity是一个自定义类。但是也会报错,把析构函数改成如下, delete []m_pEntries就可以了。不会报错。
因为StreamEntrity是自定义类,在创建的时候用new StreamEntrity[]的方式创建的,delete[]也需要成对,但是为什么直接delete
会报错呢? 看C++ delete操作报错(二)吧。