使用 Arrow 调试代码#

Arrow C++ 的 GDB 扩展#

默认情况下,当被要求打印 C++ 对象的值时,GDB 会显示其成员变量的内容。但是,对于 C++ 对象来说,这通常不会产生非常有用的输出,因为 C++ 类倾向于将其实现细节隐藏在方法和访问器后面。

例如,以下是如何在 GDB 中显示 arrow::Status 实例

$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++ 类提供美观打印

还涵盖了重要的实用程序类