前面我们说了new在分配空间的一些细节,这里作一些补充。其实我们在调用new时,在他的地层重载运算符里面是这样实现的:
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
_STD _Nomemory();
return (p);
可以看出它是直接调用了我们C语言中常用的malloc函数来实现。由此我们可以知道malloc也同样会分配一个块头。32Byte + dataSize + 4( 0xfdfdfdfd )这么大的一个空间。
我们再来看看delete,它的实现是:
_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;
这里我们注意到一点,在第一个用红色字体显示的if里面是检查了UserData是否为空。所以我们便又得出一个结论:delete某个指针的时候,在delete之前我们是不用去检查这个指针是否为空的。通常我们都会这样写:
if ( p != NULL )
delete p;
当然这里的习惯是好的,但是我们得清楚这里的空判断是可以不要的。
我们再看看下边一句红色的部分调用的是_free_dbg, 由此我们又想到了C语言中常用的free。于是我们看看free的实现,我们知道了,在free里面它是直接调用了_free_dbg,这里我们又得想到,free没有去检查UserData是否为空,直接就进行释放 - -。。。我们就必须得这么写了:
if ( p != NULL )
free( p );
在之后就进行了一系列的检查,这里面处理块头两指针类似一个链表,操作是这样的:
if (pHead->pBlockHeaderNext)
{
pHead->pBlockHeaderNext->pBlockHeaderPrev = pHead->pBlockHeaderPrev;
}
else
{
_ASSERTE(_pLastBlock == pHead);
_pLastBlock = pHead->pBlockHeaderPrev;
}
if (pHead->pBlockHeaderPrev)
{
pHead->pBlockHeaderPrev->pBlockHeaderNext = pHead->pBlockHeaderNext;
}
else
{
_ASSERTE(_pFirstBlock == pHead);
_pFirstBlock = pHead->pBlockHeaderNext;
}
这样就移除了当前要释放的内存块结点。很容易看出跟链表删除结点是一样的。。
之后的操作就是:
memset( pHead, _bDeadLandFill,
sizeof( _CrtMemBlockHeader ) + pHead->nDataSize + nNoMansLandSize );
清空当前分配块的整个空间,蓝色的字体的定义是:static unsigned char _bDeadLandFill = 0xDD;
以0xDD来填充。之后就是一些收尾工作。。。大致就到这里就给释放掉了 - -
所以呢,new和malloc, delete和free他们的联系是很紧密的。也是为了C++兼容C的吧。。
说的有什么不对的地方望大家多多指教。。。。