R:如何使 dump.frames() 包含所有变量以供以后使用 debugger() 进行 post-mortem 调试

R: How make dump.frames() include all variables for later post-mortem debugging with debugger()

我有以下代码会引发错误并使用 dump.frames() 作为 proposed e. g. by Hadley Wickham 写入所有帧的转储:

a <- -1
b <- "Hello world!"
bad.function <- function(value)
{
  log(value)                  # the log function may cause an error or warning depending on the value
}

tryCatch( {
             a.local.value <- 42
             bad.function(a)
             bad.function(b)
          },
          error = function(e)
          {
            dump.frames(to.file = TRUE)
          })

当我重新启动 R 会话并加载转储以通过

调试问题时
load(file = "last.dump.rda")
debugger(last.dump)

我在框架中的任何地方都找不到我的变量(a、b、a.local.value)和我的函数 "bad.function"。

这让转储对我来说几乎一文不值。

我需要做什么才能看到我的所有变量和函数以进行体面的 post-mortem 分析

debugger的输出是:

> load(file = "last.dump.rda")
> debugger(last.dump)
Message:  non-numeric argument to mathematical functionAvailable environments had calls:
1: tryCatch({
    a.local.value <- 42
    bad.function(a)
    bad.function(b)
2: tryCatchList(expr, classes, parentenv, handlers)
3: tryCatchOne(expr, names, parentenv, handlers[[1]])
4: value[[3]](cond)

Enter an environment number, or 0 to exit  
Selection: 

PS:我正在使用 R3.3.2 和 RStudio 进行调试。

2016 年 11 月 20 日更新: 请注意,它 不是 R 错误(请参阅 Martin 的回答麦克勒)。我没有改变可重复性的答案。所描述的解决方法仍然适用。

总结

如果您想在新的 R 会话中调试批处理作业的错误,我认为 dump.frames(to.file = TRUE) 当前 R 中的一个反模式(或者可能是一个错误)。

你最好把它换成

  dump.frames()
  save.image(file = "last.dump.rda")

options(error = quote({dump.frames(); save.image(file = "last.dump.rda")}))

而不是

options(error = dump.frames)

因为全局环境(.GlobalEnv = 您通常创建对象的用户工作区)包含在转储中,而当您直接通过 dump.frames(to.file = TRUE) 保存转储时它丢失了。

影响分析

如果没有 .GlobalEnv,您将丢失重要的顶级对象(及其当前值 ;-) 以了解导致错误的代码行为!

特别是在 "non-interactive" R 批处理作业 中出现错误的情况下,没有 .GlobalEnv 你就迷路了,因为你只能在新启动的(空)中进行调试交互式工作区,您只能在其中访问调用堆栈框架中的对象。

使用上面的代码片段,您可以像往常一样在新的 R 工作区中检查导致错误的对象值:

load(file = "last.dump.rda")
debugger(last.dump)

背景

dump.frames 的实现在工作区中创建了一个变量 last.dump 并用调用堆栈的环境填充它(sys.frames()。每个环境包含 "local variables"被调用函数)。然后使用 save().

将此变量保存到文件中

帧堆栈(调用堆栈)随着函数的每次调用而增长,参见?sys.frames:

.GlobalEnv is given number 0 in the list of frames. Each subsequent function evaluation increases the frame stack by 1 and the [...] environment for evaluation of that function are returned by [...] sys.frame with the appropriate index.

观察 .GlobalEnv 的索引号为 0。

如果我现在开始调试由问题中的代码和 select 帧 1(不是 0!)生成的转储,我可以看到一个变量 parentenv,它指向(引用).GlobalEnv:

Browse[1]> environmentName(parentenv)
[1] "R_GlobalEnv"

因此我相信 sys.frames 不包含 .GlobalEnv 因此 dump.frames(to.file = TRUE) 也不包含因为它只存储 sys.frames 而没有 [=16 的所有其他对象=].

也许我错了,但这看起来像是一个不需要的效果,甚至是一个错误。 欢迎讨论!

参考资料

https://cran.r-project.org/doc/manuals/R-exts.pdf

摘自第 4.2 节调试 R 代码(第 96 页):

Because last.dump can be looked at later or even in another R session, post-mortem debug- ging is possible even for batch usage of R. We do need to arrange for the dump to be saved: this can be done either using the command-line flag --save to save the workspace at the end of the run, or via a setting such as

options(error = quote({dump.frames(to.file=TRUE); q()}))

请注意,与 R 核心团队一起工作通常比仅仅告诉 R 有一个错误更有效率。它显然没有错误,因为它的行为与文档中的完全一致。

如果您以交互方式工作也没有问题,因为您可以完全访问那里的工作区(可能是 LARGE),因此该问题仅适用于批处理作业(正如你所提到的)。

我们这里有一个缺失的功能,功能请求(和错误报告!)应该在 R 错误站点(又名 _'R bugzilla')上发生,https://bugs.r-project.org/ ... typically however after having read the corresponding page on the R website: https://www.r-project.org/bugs.html.

请注意,R bugzilla 是可搜索的,在当前情况下,您很快就会发现 Andreas Kersting 提出了一个不错的建议(即作为一个愿望,而不是声称存在错误), https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17116 因此,我已经在 8 月 16 日将缺少的功能添加到 R 中。 是的,当然是 R 的 开发版本 ,又名 R-devel。 另请参阅 R-devel 邮件列表中的今天主题, https://stat.ethz.ch/pipermail/r-devel/2016-November/073378.html