卸载动态库需要两个dlclose()调用吗?

时间:2012-01-09 18:10:31

标签: objective-c c macos cocoa dylib

我有一个动态库,我使用dlopen()加载,然后使用dlclose()卸载;

如果我不包含任何目标c代码dlopen()需要一个dlclose()调用,这是预期的行为。但是当我将任何目标c代码包含在目标中时,我遇到问题,我需要对加载的库进行两次dlclose()调用才能卸载。

这是预期的行为吗?我该如何解决?

1 个答案:

答案 0 :(得分:29)

我意识到您使用的是dlopen,而不是CFBundleNSBundle。不过, 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两次,你应该会发生不好的事情。

相关问题