我有一个动态库,我使用dlopen()
加载,然后使用dlclose()
卸载;
如果我不包含任何目标c代码dlopen()
需要一个dlclose()
调用,这是预期的行为。但是当我将任何目标c代码包含在目标中时,我遇到问题,我需要对加载的库进行两次dlclose()
调用才能卸载。
这是预期的行为吗?我该如何解决?
答案 0 :(得分:29)
我意识到您使用的是dlopen
,而不是CFBundle
或NSBundle
。不过, Code Loading Programming Topics 手册说明了这一点:
在Cocoa应用程序中,您不应使用
CFBundle
例程来加载和卸载可执行代码,因为CFBundle
本身不支持Objective-C运行时。NSBundle
正确地将Objective-C符号加载到运行时系统中,但由于运行时限制,无法在加载后卸载Cocoa包。
和此:
由于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
两次,你应该会发生不好的事情。