在用到delete的時候,我們往往會針對類對象與類對象數組做不同刪除,在這背后編譯器是如何做的?
#include<iostream> using namespace std; class A{ int a; public: ~A(){ printf("delete A\n"); } }; int main(){ A *pa = new A ; A *pas = new A[10] ; //delete []pas; //詳細流程 //delete []pa; //會發生什么 //delete pas; //會怎么樣 getchar(); }
從匯編的角度來看:在C++的delete與delete[]對應'scalar deleting destructor'或 'vector deleting destructor'
void scalar_deleting_destructor(A* pa) { pa->~A(); A::operator delete(pa); } void vector_deleting_destructor(A* pa, size_t count) { for (size_t i = 0; i < count; ++i) pa[i].~A(); A::operator delete[](pa); }
//delete []pas; //會調用10次析構函數在free
//delete []pa; //超出范圍的內存會被收回,VS: 編譯正確,運行出錯
//delete pas; //會怎么樣,VS: 編譯通過,運行報錯 VC:編譯通過,可以運行,但只調用一次析構函數
一下用於VS的解釋:
參考
好,現在討論在VS下用delete刪除一個對象數組指針時報錯的問題。
根據報錯,我們會跟到一個dbgdel.cpp文件中,
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
先看一個數據結構定義:就是DEBUG下系統對內存進行管理的一個數據結構:
_CrtMemBlockHeader * pHead;
typedef struct _CrtMemBlockHeader
{
struct _CrtMemBlockHeader * pBlockHeaderNext;
struct _CrtMemBlockHeader * pBlockHeaderPrev;
char * szFileName;
int nLine;
#ifdef _WIN64
/* These items are reversed on Win64 to eliminate gaps in the struct
* and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is
* maintained in the debug heap.
*/
int nBlockUse;
size_t nDataSize;
#else /* _WIN64 */
size_t nDataSize;
int nBlockUse;
#endif /* _WIN64 */
long lRequest;
unsigned char gap[nNoMansLandSize];
/* followed by:
* unsigned char data[nDataSize];
* unsigned char anotherGap[nNoMansLandSize];
*/
} _CrtMemBlockHeader;
可以看出來,這是一個雙向的鏈表,(每一個結構中都包含一個pre和next指針)。 還包含如下信息: 申請空間的文件名、所在行數、用戶申請的數據大小, 內存塊的類型,用於內存管理信息的額外空間。
現在來看出錯的斷言:
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
我們傳進去的參數, pHead->nBlockUse的值為147 看看是如何判斷一個內存塊的是否是合法的。
#define _BLOCK_TYPE_IS_VALID(use) (_BLOCK_TYPE(use) == _CLIENT_BLOCK || \
(use) == _NORMAL_BLOCK || \
_BLOCK_TYPE(use) == _CRT_BLOCK || \
(use) == _IGNORE_BLOCK)
而BLOCK_TYPE(use)又是怎么的宏定義呢:
#define _BLOCK_TYPE(block) (block & 0xFFFF)
我們的參數穿進去之后,還是147啊。 而
CLIENT_BLOCK 4 NORMAL_BLOCK 1 CRT_BLOCK 2 IGNORE_BLOCK 3
沒一個條件能成立,所以斷言不成立,系統就會彈出那么大的錯誤提示框。
但是為什么我們穿進去的參數會是147呢?
參考:http://m.oschina.net/blog/55763