使用 Arrow 偵錯程式碼#

Arrow C++ 的 GDB 擴充功能#

預設情況下,當要求列印 C++ 物件的值時,GDB 會顯示其成員變數的內容。然而,對於 C++ 物件來說,這通常不會產生非常有用的輸出,因為 C++ 類別傾向於將其實作細節隱藏在方法和存取器之後。

例如,以下是 arrow::Status 實例可能由 GDB 顯示的方式

$3 = {
  <arrow::util::EqualityComparable<arrow::Status>> = {<No data fields>},
  <arrow::util::ToStringOstreamable<arrow::Status>> = {<No data fields>},
  members of arrow::Status:
  state_ = 0x0
}

這是 arrow::Decimal128Scalar

$4 = (arrow::Decimal128Scalar) {
  <arrow::DecimalScalar<arrow::Decimal128Type, arrow::Decimal128>> = {
    <arrow::internal::PrimitiveScalarBase> = {
      <arrow::Scalar> = {
        <arrow::util::EqualityComparable<arrow::Scalar>> = {<No data fields>},
        members of arrow::Scalar:
        _vptr.Scalar = 0x7ffff6870e78 <vtable for arrow::Decimal128Scalar+16>,
        type = std::shared_ptr<arrow::DataType> (use count 1, weak count 0) = {
          get() = 0x555555ce58a0
        },
        is_valid = true
      }, <No data fields>},
    members of arrow::DecimalScalar<arrow::Decimal128Type, arrow::Decimal128>:
    value = {
      <arrow::BasicDecimal128> = {
        <arrow::GenericBasicDecimal<arrow::BasicDecimal128, 128, 2>> = {
          static kHighWordIndex = <optimized out>,
          static kBitWidth = 128,
          static kByteWidth = 16,
          static LittleEndianArray = <optimized out>,
          array_ = {
            _M_elems = {[0] = 1234567, [1] = 0}
          }
        },
        members of arrow::BasicDecimal128:
        static kMaxPrecision = 38,
        static kMaxScale = 38
      }, <No data fields>}
  }, <No data fields>}

幸運的是,GDB 也允許自訂擴充功能來覆寫特定類型的預設列印方式。我們提供了一個以 Python 撰寫的 GDB 擴充功能,可為常見的 Arrow C++ 類別啟用美化列印,以便實現更有效率的偵錯體驗。例如,以下是上述 arrow::Status 實例將會顯示的方式

$5 = arrow::Status::OK()

這是與上述相同的 arrow::Decimal128Scalar 實例

$6 = arrow::Decimal128Scalar of value 123.4567 [precision=10, scale=4]

手動載入#

若要為 Arrow 啟用 GDB 擴充功能,您可以簡單地從您的電腦上的某個位置下載它,並從 GDB 提示符號中 source

(gdb) source path/to/gdb_arrow.py

您將必須在每個新的 GDB 會期中 source 它。您可能希望透過在 gdbinit 檔案中新增 source 調用來使其成為隱含的。

自動載入#

GDB 提供了一種機制,可以為每個涉及偵錯會期的物件檔案或程式庫自動載入腳本或擴充功能。您將需要

  1. 找出您的 GDB 安裝的自動載入位置。可以使用 GDB 提示符號上的 show 子命令來確定這一點;答案將取決於作業系統。

    以下是 Ubuntu 上的範例

    (gdb) show auto-load scripts-directory
    List of directories from which to load auto-loaded scripts is $debugdir:$datadir/auto-load.
    (gdb) show data-directory
    GDB's data directory is "/usr/share/gdb".
    (gdb) show debug-file-directory
    The directory where separate debug symbols are searched for is "/usr/lib/debug".
    

    這告訴您用於自動載入的目錄是 $debugdir$datadir/auto-load,它們展開為 /usr/lib/debug//usr/share/gdb/auto-load

  2. 找出 Arrow C++ DLL 的完整路徑,並解析所有符號連結。例如,您可能已在 /usr/local 中安裝 Arrow 7.0,然後 Arrow C++ DLL 的路徑可能是 /usr/local/lib/libarrow.so.700.0.0

  3. 確定實際的自動載入腳本路徑。它的計算方式是 a) 取得您選擇的自動載入目錄的路徑,b) 附加 Arrow C++ DLL 的完整路徑,c) 在尾部附加 -gdb.py

    在上面的範例中,如果我們選擇 /usr/share/gdb/auto-load 作為自動載入目錄,則自動載入腳本的完整路徑必須是 /usr/share/gdb/auto-load/usr/local/lib/libarrow.so.700.0.0-gdb.py

  4. 複製或符號連結 GDB 擴充功能 到步驟 3 中確定的檔案路徑。

如果一切順利,那麼一旦 GDB 遇到 Arrow C++ DLL,它將自動載入 Arrow GDB 擴充功能,以便在顯示提示符號上美化列印 Arrow C++ 類別。

支援的類別#

Arrow GDB 擴充功能為核心 Arrow C++ 類別提供美化列印

重要的公用程式類別也涵蓋在內