用推文回太長了, 所以單獨回這段
推 dreamboat66: 所以exe跟dll會allicate在不同的heap這講法是錯的嗎
應該說,和 exe/dll 沒有因果關係。
另一方面,就算是所謂的 "同一個 exe" 內,也不見得保證使用相同的 heap。
連結 dynamic/static link library 不會有什麼不同而造成各自獨立的 heap。
差別只是載入與解析 symbol 的時機不同。事實上,malloc 根本就無法分辨是被
exe 或是 dll 呼叫,所以要從不同的 heap 來配置。例如
main (a.out)
-> foo (libfoo.so)
-> bar (a.out)
-> malloc (libc.so)
在這樣的 call chain 下,malloc 該從哪個 heap 配置呢?
一般來說,會各自動態連結 runtime library (ex: msvcrt.dll/libc.so)。
之後 loader 又將同一個 process 的 exe/dll 呼叫的 malloc 解析成同一個
functoin,那就會受同一個 heap 管理。
當然也可以不同的 heap,但這是寫的人自已明確指定 heap。使不使用同一個
heap 純粹是怎麼設計資源管理上的問題,在既定的 API 規範下,可能會有不
同的實作,不需要臆測底層怎麼運作寫出不 portable 的 code ,就像正常不
會想能不能把 fopen 出來的東西用 POSIX close() 或 Windows 的 CloseHandle()
去關閉一樣。
使用獨立的 heap 通常有幾個考量
1. 避免 resource leak。例如在 delete 掉一個複雜的 object 後, 自動把所有
透過他 allocate 出來的其他 object 一並 release
2. 避免 fragment 。如果 allocate 出來的 object 大小都一樣,可以減少記錄
used/free 區塊大小的 overhead
3. 其他。例如 stack allocator。對有 first in last out 特性的 allocate 方式
可以減少追蹤分散的 free-list 的 overhead。
4. 避免 thread contention
這些考量都跟動態 library 沒有直接關係,而且 (2) (4) 在現代的 memory allocator
實作多少都可以有一定程度的優化
例如使用 dlopen/dlclose 在執行時期載入的第三方外掛,為了避免因為外掛本身
的 bug 造成 leak 影響主程式,也是有可能使用獨立的 heap 在 unload 時自動 free 掉整個 heap。
以 Windows 為例
HANDLE myHeap;
BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle,
IN DWORD nReason,
IN LPVOID Reserved) {
BOOLEAN bSuccess = TRUE;
switch (nReason) {
case DLL_PROCESS_ATTACH:
myHeap = HeapCreate(0, SIZE_OF_INIT, SIZE_OF_MAX);
break;
case DLL_PROCESS_DETACH:
HeapDestroy(myHeap);
break;
}
}
配置時不直接使用 malloc, 而是使用 HeapAlloc
ptr = HeapAlloc(myHeap, 0, sizeof(obj));
在 Linux 的話,類似的機制可以用 constructor/destructor 來初始獨立的 heap,
以 dlmalloc 的 mspace 為例,使用起來大略是像這樣
mspace ms;
__attribute__ ((constructor))
void foo_load () {
ms = create_mspace(....);
}
__attribute__ ((destructor))
void foo_unload () {
destroy_mspace(ms);
}
配置時則是使用
mspace_malloc(ms, bytes)