如果您是使用 Arrow 代码的开发人员,该包对 tidy eval 和 C++ 的使用需要一个可靠的调试策略。在本文中,我们推荐几种方法。
在段错误后获取更具描述性的 C++ 错误消息
如果您在 RStudio IDE 中工作,如果出现段错误,您的 R 会话将被中止。如果您在命令行 R 会话中重新运行代码,则会话不会自动中止,因此可以复制段错误附带的错误消息。这是一个在撰写本文时存在的错误示例。
> S3FileSystem$create()
*** caught segfault ***
address 0x1a0, cause 'memory not mapped'
Traceback:
1: (function (anonymous, access_key, secret_key, session_token, role_arn, session_name, external_id, load_frequency, region, endpoint_override, scheme, background_writes) { .Call(`_arrow_fs___S3FileSystem__create`, anonymous, access_key, secret_key, session_token, role_arn, session_name, external_id, load_frequency, region, endpoint_override, scheme, background_writes)})(access_key = "", secret_key = "", session_token = "", role_arn = "", session_name = "", external_id = "", load_frequency = 900L, region = "", endpoint_override = "", scheme = "", background_writes = TRUE, anonymous = FALSE)
2: exec(fs___S3FileSystem__create, !!!args)
3: S3FileSystem$create()
此输出提供了 R 追溯;但是,它没有提供任何有关段错误源自的 C++ 代码的确切行的信息。为此,您需要在附加 C++ 调试器的情况下运行 R。
在附加 C++ 调试器的情况下运行 R 代码
由于 Arrow 的核心是 C++ 代码,因此当错误源自 C++ 而不是 R 层时,调试代码有时会很棘手。如果您添加触发 C++ 错误的新代码(或在现有代码中找到一个错误),这可能会导致段错误。如果您在 RStudio 中工作,则会话将中止,并且您可能无法检索诊断和/或报告错误所需的错误消息。解决此问题的一种方法是找到导致错误的代码,并在附加 C++ 调试器的情况下运行 R。
如果您使用的是 macOS 并且已使用 Apple 安装程序安装了 R,则将无法在附加调试器的情况下运行 R;有关此问题的原因和解决方法的详细信息,请参阅此处的说明。
首先,使用调试器加载 R。最常见的调试器是 gdb
(通常在 Linux 上找到,有时在 macOS 上找到,或通过 MinGW 或 Cygwin 在 Windows 上找到)和 lldb
(默认的 macOS 调试器)。
在我的情况下是 gdb
,但如果您使用的是 lldb
调试器(例如,如果您在 Mac 上),只需在此处交换该命令即可。
R -d gdb
接下来,运行 R。
run
您现在应该在一个附加了 C++ 调试器的 R 会话中。这看起来类似于普通的 R 会话,但会有一些额外的输出。
现在,运行您的代码 - 直接在会话中运行或从文件中获取它。如果代码导致段错误,您将获得额外的输出,您可以使用它来诊断问题或将其作为额外信息附加到问题中。
这是前一个示例中所示的段错误的调试器输出。您可以在此处看到触发段错误的确切行包含在输出中。
> S3FileSystem$create()
Thread 1 "R" received signal SIGSEGV, Segmentation fault.
0x00007ffff0128369 in std::__atomic_base<long>::operator++ (this=0x178) at /usr/include/c++/9/bits/atomic_base.h:318
318 operator++() noexcept
延伸阅读
以下资源提供了调试 R 代码的详细指南
有关在 R 中使用 C++ 调试器的出色深入指南,请参阅David Vaughan 的这篇博文。
您可以在LLDB 网站上找到等效的 gdb
和 lldb
命令列表。