跳到內容

如果您是使用 Arrow 程式碼的開發人員,套件對 tidy eval 和 C++ 的使用需要可靠的除錯策略。在本文中,我們推薦幾種方法。

除錯 R 程式碼

一般來說,我們發現使用互動式除錯(例如呼叫 browser()),您可以在特定環境中檢查物件,比使用更簡單的技術(例如 print() 陳述式)更有效率。

在區段錯誤後取得更詳細的 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

如果您的會話掛起,取得除錯器輸出

當發生區段錯誤時,上述指示可以提供有價值的額外上下文。但是,偶爾會有錯誤可能導致您的會話無限期掛起而沒有區段錯誤的情況。在這種情況下,中斷除錯器並從所有執行緒產生回溯追蹤可能在診斷上很有用。

要做到這一點,首先,按下 Ctrl/Cmd 和 C 以中斷除錯器,然後執行

thread apply all bt

這將產生大量輸出,但此資訊在識別問題原因時很有用。

延伸閱讀

以下資源提供 R 程式碼除錯的詳細指南

如需關於在 R 中使用 C++ 除錯器的優秀深入指南,請參閱 David Vaughan 的這篇部落格文章。

您可以在 LLDB 網站上找到 gdb 和 lldb 等效命令的清單。