class下的new delete

class test
{
public:
    test(){printf("constructor/n");};
    ~test() {printf("destuctor/n");}
};

void main()
{
    test *t = new test[12];
    delete t;

}

vc6編譯,ida反編譯如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *v3; // eax@1
  int result; // eax@2
  int v5; // esi@2
  void *v6; // esi@5

  v3 = operator new(0x10u);
  if ( v3 )
  {
    v5 = (int)((char *)v3 + 4);
    *(_DWORD *)v3 = 12;  //數組長度,放在開闢空間的前四個字節
    _eh_vector_constructor_iterator_((char *)v3 + 4, 1, 12, sub_401090, sub_4010B0);
    //sub_401090爲構造函數,sub_4010B0爲析構
    result = v5;  //開闢出空間的第5個字節地址返回給test *t
  }
  else
  {
    result = 0;
  }
  if ( result )   //編譯優化後的delete,先判斷result是否爲空,所以很多人習慣寫的if (t!=null) delete t是沒必要的
  {
    v6 = (void *)(result - 4);
    _eh_vector_destructor_iterator_(result, 1, *(_DWORD *)(result - 4), sub_4010B0);
    result = sub_4010C0(v6);  //刪除內存,內部直接調用的heapfree,沒有對free的調用
  }
  return result;
}

對new的調用,我們可以看到vc6確實是在爲非內置類型數據成員開闢空間的時候,多開闢了一個長度,而且長度是放在這開闢出來內存的前四個字節中,相當於調用了malloc(size+4),然後全部執行構造函數

但是delete調用就不一樣了,這裏沒有對free函數的調用,因爲他多了一個代表長度的字節,沒法用原有的庫函數了,只能從寫了一個方法

綜上,

1,delete 加不加[]對系統內置類型int double之類,沒有關係,這個情況下new delete最終是和malloc free調用同樣的代碼

2,非內置類型的情況下,delete 纔是一定加[],雖然到現在我還是不明白,爲什麼不可以學習free的方式使用__sbh_find_block等函數獲取實際大小,然後根據大小來析構,難道是以空間換時間?

所以說new必然調用malloc是可以的,delete必然調用free是不正確的,或許在不同的編譯器下面有不同的表現,歡迎高手指教



發佈了30 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章