2016-11-04 57 views
3

我有以下代码将产生一个错误,并写入使用所有帧的转储dump.frames()proposed e. g. by Hadley WickhamR:如何使dump.frames()包括后来验尸调试所有变量与调试器()

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”任何地方在框架中。

这使得转储几乎对我毫无价值。

我需要做些什么才能看到我所有的变量和功能验后分析

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进行调试。

+0

选择1,然后做'LS(parentenv)'或'得到( “a.local.value”,ENV = parentenv)'。 –

+0

罢工,获得本地变量的方式,thx!当我浏览包含在转储的不同框架中的所有环境时,我仍然无法找到的是全局变量和函数。奇怪......它看起来像'.GlobalEnv'不包含在'dump.frames'中。 –

+0

也许人们可以将额外的变量添加到转储的.rda文件中? –

回答

1

注意,它往往是更高效地使用将R核心团队,而不是仅仅告诉的是,R有一个错误的工作。在这里,它显然没有错误,因为它的行为与记录完全相同。

如果您以交互方式工作,因为您可以完全访问工作空间(可能是LARGE),所以此问题仅适用于批处理作业(如您所述)。

我们宁愿在这里是一个功能缺失和功能要求(和bug报告!)应该发生在R漏洞的网站(又名_'R的Bugzilla“),https://bugs.r-project.org/ ......但是通常在读完后R网站上的相应页面:https://www.r-project.org/bugs.html

注意的是,R Bugzilla的是搜索,而在目前的情况下,你会很快发现,安德烈亚斯Kersting打了一个漂亮的提案(即作为一个心愿,而不是声称一个bug), 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

+0

Martin,感谢您的耐心帮助我学习如何搜索并提出缺失的功能(我不太了解或者更好的还没有关注)。我已经将答案标记为已接受,我很高兴在未来的版本中已经有了解决方案。请放心,我不想责怪R或某些开发人员大声喊出“bug”! –

3

更新2016年11月20日:请注意,这是不的R错误(见马丁Maechler的答案)。我没有改变我的答案重现性。所描述的解决方法仍然适用。

摘要

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

你应该更好地与

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

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

,而不是

取代它,因为全球环境(.GlobalEnv =用户工作区,你通常创建对象)然后包含在转储中,而在保存转储目录时缺失通过dump.frames(to.file = TRUE)

影响分析

没有.GlobalEnv你失去重要的顶层对象(和它们的当前值;-)了解你的代码导致错误的行为!

尤其是在你不.GlobalEnv失去“非交互式” R批处理作业时出现错误的情况下,由于可以调试只能在重新启动(空)的交互式工作空间,你则只能访问呼叫的对象堆栈帧。

使用代码片段上方可以检查对象值,导致该错误在通过新的R的工作区照例:

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

背景

dump.frames的实现创建在一个变量last.dump工作空间并用调用堆栈的环境填充(sys.frames()。每个环境都包含被调用函数的“局部变量”)。然后使用save()将此变量保存到文件中。

帧堆栈(调用栈)生长用函数的每个调用,见?sys.frames

.GlobalEnv在帧列表被给定数目的0。随后的每一个 功能评估增加帧堆栈1,评估该功能的环境由sys.frame返回适当的索引。

可观察到.GlobalEnv具有索引号0

如果现在开始调试通过在问题的代码所产生的转储和选择帧1(不是0!)我可以看到一个可变parentenv这点(参考)的.GlobalEnv

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

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

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

参考

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

从部分摘录4.2调试R代码里面(第96页):

因为last.dump可以在稍后的或甚至在另一个R对话看着, 即使对R的批量使用也可以进行验尸调试。我们确实需要为 保存转储:这可以通过 使用命令行标志 --save保存工作区在运行结束时,或经由设置如

选项(误差=报价({dump.frames(to.file = TRUE ); Q()}))

+0

不确定自发布此答案后情况是否发生了变化,但是当我[查找调试器](https://stat.ethz.ch/R-manual/R-devel/library/utils/html/debugger.html)时,我在''查看'include.GlobalEnv'选项中看到' dump.frames'。这与您提出的解决方案相同吗? – rensa

+1

@rensa在我发布之前,我通过FR(https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17116)创建了参数'include.GlobalEnv'(我忽略了这个FR) 。这个参数的语义与我提出的解决方案有所不同:为了从GlobalEnv获得一个变量,你可以使用get(“variable.name”,last.dump $ .GlobalEnv)'如果你使用这个参数创建转储,而只是输入调试器中的变量名不会**通过“攀爬”调用堆栈来找到变量 - 这是我最后一次了解的信息。我的解决方法实际上导致在GlobalEnv中找到该变量。 –