我有一个动态库,使用dlopen()
加载,然后使用dlclose()
卸载;
如果我没有包含任何Objective-C代码,则dlopen()
需要一个dlclose()
调用,这是预期的行为。但是,当我将任何Objective-C代码添加到目标中时,我遇到了问题,需要进行两个dlclose()
调用才能卸载已加载的库。
这是一种预期行为吗?我该如何解决它?
我有一个动态库,使用dlopen()
加载,然后使用dlclose()
卸载;
如果我没有包含任何Objective-C代码,则dlopen()
需要一个dlclose()
调用,这是预期的行为。但是,当我将任何Objective-C代码添加到目标中时,我遇到了问题,需要进行两个dlclose()
调用才能卸载已加载的库。
这是一种预期行为吗?我该如何解决它?
虽然我意识到您正在使用的是 dlopen
,而不是 CFBundle
或者 NSBundle
。然而,《加载代码编程主题》手册中写道:
在Cocoa应用程序中,不应该使用
CFBundle
函数来加载和卸载可执行代码,因为CFBundle
不支持 Objective-C 运行时。NSBundle
可以正确地将 Objective-C 符号加载到运行时系统中,但由于运行时限制,没有方法可以卸载 Cocoa 组件包。
以及:
由于 Objective-C 运行时系统的限制,
NSBundle
无法卸载可执行代码。
这使我怀疑当您加载库时,它会向 Objective-C 运行时注册自己,然后运行时会再次调用 dlopen
(或以某种方式增加库的引用计数)。
我搜索了 Objective-C 运行时源代码,并找到了这个:
// 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
两次,那么会出现问题。