作者tropical72 (藍影)
看板C_and_CPP
標題Re: [問題] delete / new , free / malloc
時間Thu Jan 12 04:40:02 2012
這篇回覆實驗性質頗重,看笑話的網友請海涵,
觀念有誤請指正。
花了點時間看系列文,發現源起是 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