R 包在卸载时必须卸载动态库吗?

Posted

技术标签:

【中文标题】R 包在卸载时必须卸载动态库吗?【英文标题】:Must R Packages Unload Dynamic Libraries When They Unload? 【发布时间】:2014-12-28 18:56:26 【问题描述】:

来自 Hadley 的 C best practices

与 C++ 一样,无论何时在包中使用 C 代码,都应在卸载包时卸载 DLL:

.onUnload <- function (libpath) 
  library.dynam.unload("mypackage", libpath)

另一方面,

Writing R Extensions 甚至没有提到这一点。我可以看到卸载 dll 是多么有礼貌,但是这样做似乎会给我带来一些奇怪的问题,即加载/卸载/重新加载的包(参见下面的示例)。此外,还有一些提及表明可能不需要卸载。来自?library.dynam

请注意,是否可以卸载 DLL 然后重新加载同一文件的修订版本取决于操作系统:请参阅 dyn.unload 帮助的“值”部分。

虽然这不应该影响未修改的对象。然后是Brian Ripley in R-devel的这条评论:

说了这么多,我的经验是,如果您需要再次加载 DLL,卸载 DLL 通常无济于事(这就是为什么例如 tcltk 不卸载其 DLL)。

那么让 C 库加载是否可以接受?我宁愿不必深入研究为什么会发生以下情况(在我开始卸载库之前没有发生)。

R version 3.1.1 (2014-07-10)
Platform: x86_64-apple-darwin13.1.0 (64-bit)

> library(alike)       # install_github("brodieg/alike", ref="fdaa578e"), if you're curious
> library(data.table)
data.table 1.9.2  For help type: help("data.table")
> detach("package:data.table", unload=T)
> detach("package:alike", unload=T)
> library(alike)
> library(data.table)
Error : .onLoad failed in loadNamespace() for 'data.table', details:
  call: address(x)
  error: object 'Caddress' not found
In addition: Warning messages:
1: In FUN(X[[9L]], ...) :
  failed to assign RegisteredNativeSymbol for alike to alike since alike is already defined in the ‘data.table’ namespace
2: In FUN(X[[9L]], ...) :
  failed to assign RegisteredNativeSymbol for typeof to typeof since typeof is already defined in the ‘data.table’ namespace
3: In FUN(X[[9L]], ...) :
  failed to assign RegisteredNativeSymbol for type_alike to type_alike since type_alike is already defined in the ‘data.table’ namespace
Error: package or namespace load failed for ‘data.table’

这些警告都与alike 函数有关。 alike没有用来卸载它的动态库,也没有出现上述错误。在我实施卸载后,错误开始发生。请注意,data.table 1.9.2 没有卸载其 DLL,尽管其他也没有卸载 DLL 的包不会导致此问题。 data.table 1.9.4 工作正常。

【问题讨论】:

我知道这是您的问题,但您是否找到任何有关此的其他信息? @Dason,不怕。我还遇到了this issue 和data.table,这可能相关也可能不相关。此外,我实际上已经有一段时间没有遇到这个问题了,但是已经发生了太多变化,无法确切知道是什么解决了它。 很奇怪。我有自动卸载的习惯,因为我一直被调试错误版本的 DLL 所困扰,我忘记卸载了。工作流程是:加载包,查找错误,修复,重新加载包。但是 DLL 没有被卸载。埃普斯。因此,Hadley 的建议对开发人员来说是极好的。但我从未在野外见过像你这样的问题。有趣的东西。 那么您是在问基于意见的问题“我应该这样做吗”,还是在问主题问题“我如何卸载然后重新加载 DLL 而不会出现这些错误”,答案可能是“不”? 这似乎有点相关(可能重复?):***.com/a/6979989/7411272 【参考方案1】:

通常卸载 DLL 是个好主意。它拥有的资源将被完全释放,重新加载将不是问题。

在 R 中,存在 R 环境的复杂性,因为即使卸载了 DLL,也可能在 R 运行时中留下一些知识。在这种情况下,结果可能是重新加载的 DLL 库与旨在了解 DLL 状态的 R 变量不共享相同的推断状态,从而发生错误。

我认为可以安全地卸载 R 包(DLL 和 R 代码),但让 DLL 处于加载状态会更容易,除非您发现资源使用量特别大。

【讨论】:

是的。如果您无法完全控制指向该库的所有指针,那么卸载该库是一个非常糟糕的主意。卸载库是一个相当不寻常的操作,许多程序从不调用 FreeLibrary()。根据经验,像 R 这样的外部包中的资源分配和解除分配是包本身的责任除非在文档中明确指定

以上是关于R 包在卸载时必须卸载动态库吗?的主要内容,如果未能解决你的问题,请参考以下文章

ubuntulinux链接库

C#中如何动态加载和卸载DLL

我们可以静态链接动态 C 库吗?

卸载应用时动态链接firebase没有打开应用商店

如何动态加载和卸载(重新加载).dll 程序集

Dotnet 工具箱DotNetCorePlugins- 动态加载和卸载 .NET 程序插件