【问题标题】:unload dynamic library needs two dlclose() calls?卸载动态库需要两个 dlclose() 调用?
【发布时间】:2012-02-06 06:20:13
【问题描述】:

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

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

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

【问题讨论】:

  • 你确定你的库不是dlopen-ed 两次以隐藏的方式吗?或者可能是一个错误-例如内存泄漏 - 正在覆盖 dlopen-ed 句柄附近的内存?
  • dlopen 在库句柄上保留引用计数。如果 dlopen 执行了两次,则需要两次 dlclose() 来卸载库。如果包含 obj-C 代码,是否可能需要动态库?在这种情况下,第一次 dlopen 可能会在您运行程序时完成
  • 是的,我敢肯定它没有 dlopened 两次。您可以在 main 中尝试一个简单的程序,使用 dlopen,然后使用具有目标 c 代码的动态库的 dlclose。
  • @Finslicer:我确信程序启动时不需要动态库。正如我所说,如果有客观的 c 代码,即使是一个简单的 main 和 dlopen 然后 dlclose 也不能按预期工作。

标签: objective-c c macos cocoa dylib


【解决方案1】:

我知道您使用的是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 两次,你应该预料到坏事会发生。

【讨论】:

    猜你喜欢
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多