看板 C_and_CPP 關於我們 聯絡資訊
這篇回覆實驗性質頗重,看笑話的網友請海涵, 觀念有誤請指正。 花了點時間看系列文,發現源起是 QQ29 誤會大了。 提供相異於 littleshan 之看法 ( L 大之回覆均精彩,值得細閱。) ※ 引述《QQ29 (我愛阿蓉)》之銘言: : new / delete vs malloc / free : 請教各位一個小問題 : 我看msdn的一個sample code : http://msdn.microsoft.com/en-us/library/windows/desktop/aa365917(v=vs.85).aspx 先拋開 new/delete 與 malloc/free 之關係, msdn 上用的這例子明顯是以 C language 為編譯, 這應是最大之誤會 - 一開始就打算不用 c++ 之運算子。 故它並不調用 new / delete ,而是使用 malloc / free, 而其範例所使用之結構體 PIP_ADAPTER_INFO 內容也實屬 POD, 與 c++ 中之 class 有所些許差異。 此時即使換 c++ 之 new, struct 裡頭全都是 POD, 扣除 allocate fail 之例外處理,我想不到對這特例而言, new/delete 與 malloc/free 有何差異。 : 這底下有一個sample : 有這行 : pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen); : 他使用了malloc : 但聽說 能用new / delete 就盡量用 這是個可以讓人爭論很久的問題,所有的「聽說」都該再「了解」背後原因。 會有此說起因大多是在於 constructor 是否會被隱喻喚起, 小處在於例外處理之部份。 在 C++,我較偏向於,POD 時採用 malloc/free 做處理, 遇到 struct (即使 struct 裡也全為 POD,沒任何 member function) 時, 則採用 new。 照我的邏輯走,會有個缺點 - 維護上並沒 new 來得容易, 看看下面這程式碼 typedef int PointType; const size_t cnt = 10; PointType *a = (PointType*)malloc(sizeof(PointType)*cnt); free(a); 但若哪天要把 PointType 換成 class 的時候這段 code 就出包了 typedef CPoint PointType; const size_t cnt = 10; PointType *a = (PointType*)malloc(sizeof(PointTYpe)*cnt); free(a); 在 malloc 那裡反而中了不會喚起 constructor 的致命傷, 推估這是被大家所推,盡量使用 new 不用 malloc 之「其中一個原因」。 至於其它的原因於此便不再深入探討。 : 所以 : 我想使用new 這operator來做 : 但有個疑問 : ulOutBufLen 這個值 有可能 "大於" sizeof(IP_ADAPTER_INFO). : 假如我用 : pAdapterInfo = (IP_ADAPTER_INFO *) new char[ulOutBufLen]; : 這樣安全嗎 : 如果沒問題的話 : 我使用 : delete pAdapterInfo; 就能把這一串連續空間標記起來嗎? : 我是不曉得他delete怎麼去判定 : 他連續空間哪一段是他配置的 : 我很怕 : delete pAdapterInfo; 只是把sizeof(IP_ADAPTER_INFO)byte的記憶體給標記 : 而實際上 : 我是需要delete 掉sizeof(IP_ADAPTER_INFO) bytes的資訊. : 相較於delete / new : malloc / free 是不是就沒這問題了? : free(pAdapterInfo) 他就是會從 這個起始位址 free到 他剛剛配置的空間的結尾. 因為 : 我看他範例就直接free了... : ps.請問有沒有什麼方式 可以驗證 我確實delete 標記掉了多少byte嗎? : 因為我也不知道我自己這樣寫有沒有問題~~ 謝謝 : 謝謝 上面這一段一直在做 malloc / new 的比較,你怕 malloc 和 new 所配置的空間不一樣 也怕 delete / free 所釋放的空間不一樣,整體來說就是怕它們對於記憶體掌握管理方 式不一樣。 不知我的理解是否正確?若是的話再繼續往下看。 我於最原始的文章之推文裡給了一道線索 - 直接下斷點追new源碼怎麼寫的。 既然你 compiler 是 vc, 來 trace vc 裡面的重點碼, 我 trace 是 dbg 版的 dll。 先看單純的 malloc 和 free,追蹤下來可以發現 ˇ malloc 實際上的核心 code 是在呼叫 _nh_malloc_dbg (dbgmalloc.c) ˇ free 實際上的核心 code 是在呼叫 _free_dbg (dbgfree.c) 過程會調用一些內部判斷機制沒錯, 若再以單純的 int *a=new int; delete a; 來追蹤 ˇ new 實際上的核心 code 是直接呼叫 malloc,只是多了判斷 malloc 回傳值是否 為 0 (也就是 malloc fail),如果 malloc 傳回 0 的話丟出 (raise) 例外 static const std::bad_alloc nomem; (new.cpp, newaop.cpp) ˇ delete 實際上的核心 code 是在呼叫 _free_dbg (dbgdel.cpp, dbgdel2.cpp) 也和 free 一樣。 --- 上面的說明只顯示了,new/delete 和 malloc/free 底層是調用的是同一套函式庫, 差在細節上有些不同,也由於細節不同 (這裡不再解析下去,再拆下去會很可怕), 所以才有一種說法: 即使對於 POD 而言, new/delete, malloc/free 還是不能混用。 甚至,我也不確定標準裡是否有明定, new/delete, malloc/free 在底層調用的函 式庫一定要同一組,所以 trace 後我也只把這個當作 vc 的一種特例而已。 ( 雖然即使標準沒明定,我想大多 compiler 也可能會貪懶底層用同一組去做 ) ---- 而再回到你的問題,如果 malloc / free 可以, 明明底層調用的是同一套 library,為何調用 new / delete 便不行? 如果你的問題是:為什麼別人說盡量用 new/delete,而這個範例是用 malloc/free, 答案是:msdn 的這個範例是要用 C compiler 的,所以避開了 C++ 的東西。 ---- 以上淺見,歡迎討論與指正。 -- 世界上有種, 不可能 轉換為 無限可能 的強大力量, 我稱它為 - 信念 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.69.239 ※ 編輯: tropical72 來自: 180.177.69.239 (01/12 04:41)
DEATHX:精彩! 01/12 09:04
xatier:推! 01/12 14:41
diabloevagto:推! 01/12 16:29
angleevil:其實這個討論,幾乎每個新手都有這疑問 01/12 17:06
angleevil:c 就用malloc/free,c++就用new/delete.至於為何c++一定 01/12 17:07
angleevil:要用new/delete.來自於建構子和解構子.很明顯發問者不知 01/12 17:07
tropical72:我想說都在查 Win32 API 了, trace 能力應該會有一點 01/12 17:23
diabloevagto:我認為c++方式最大的好處是在於呼叫ctor及dtor 01/12 20:06
diabloevagto:而且能少打幾個字xdd 01/12 20:06
hellophoenix:換個角度想,如果只是要產生物件就用new/delete;如果 01/12 23:23
hellophoenix:單純的要配置記憶體空間,用malloc/free即可 01/12 23:24
angleevil:tropical72 其實我也不太會trace.只是這個觀念會不斷 01/13 08:42
angleevil:被提出來.只是一般書和網站不會詳細講這個.所以需要你們 01/13 08:44
angleevil:幫忙新手.畢竟c++細節觀念不少. 01/13 08:45
QQ29:感謝t大解說,抱歉基礎不好,受教了 01/14 10:06