2012-01-09 39 views
7

我有一個動態庫,我加載使用dlopen(),然後卸載使用dlclose();卸載動態庫需要兩個dlclose()調用?

如果我不包括任何客觀的c代碼dlopen()需要一個dlclose()調用這是預期的行爲。但是,當我包含任何目標C代碼目標時,我有問題,我需要執行兩個dlclose()調用加載的庫來卸載。

這是一些預期的行爲?我該如何解決它?

+0

你確定你的圖書館不是以隱藏的方式進行兩次「dlopen」編輯嗎?或者可能是一個錯誤 - 例如內存泄漏 - 覆蓋「dlopen」手柄附近的內存? – 2012-01-09 18:13:10

+0

dlopen保持庫處理的引用計數。如果dlopen執行了兩次,則需要兩個dlclose()來卸載該庫。如果包含obj-C代碼,是否需要動態庫?在這種情況下,第一個dlopen可能會在您運行程序時完成 – Finslicer 2012-01-09 18:13:53

+0

是的,我相信它不會兩次跳過。你可以嘗試一個簡單的程序,主要用dlopen,然後用帶有目標c代碼的動態庫的dlclose。 – MacGeek 2012-01-09 18:26:54

回答

26

我知道您使用的是dlopen,而不是CFBundleNSBundle。儘管如此,Code Loading Programming Topics手冊這樣說:

在Cocoa應用程序,你不應該使用CFBundle程序加載和卸載可執行代碼,因爲CFBundle本身不支持Objective-C的運行時間。 NSBundle將Objective-C符號正確加載到運行時系統中,但由於運行時限制,無法卸載一次加載的可可包。

和此:

因爲在Objective-C運行系統中的限制,NSBundle不能卸載可執行代碼。

這讓我懷疑,當你到您的書架,它本身註冊Objective-C運行,並且運行時調用dlopen在圖書館試(或以某種方式增加庫的引用計數)。

我搜索了Objective-C運行的源代碼,發現this

// dylibs are not allowed to unload 
// ...except those with image_info and nothing else (5359412) 
if (result->mhdr->filetype == MH_DYLIB && _hasObjcContents(result)) { 
    dlopen(result->os.dl_info.dli_fname, RTLD_NOLOAD); 
} 

所以,是的,Objective-C的運行時在你的庫調用dlopen明確,以防止它被卸載。如果你欺騙並且撥打dlclose兩次,你應該預料會發生不好的事情。

+0

+1優秀的答案! – Till 2012-01-09 19:13:22