Linux GDB print pretty

在GDB(GNU调试器)中,set print pretty on 是一个用于格式化结构体和联合体输出的命令。它的核心作用是让GDB在打印复杂数据类型(如结构体、联合体或类)时,以更易读的缩进和换行格式显示内容,而不是将所有字段挤在一行。以下是详细解释:


1. 命令的作用

  • 默认行为
    默认情况下,GDB打印结构体或联合体时,所有字段会显示在一行中,例如:

    (gdb) p my_struct
    $1 = {field1 = 42, field2 = "hello", sub_struct = {nested_field = 3.14}}
    

    如果结构体字段较多或嵌套较深,输出会显得混乱。

  • 启用set print pretty on
    字段会按层级缩进显示,每个字段单独占一行,例如:

    (gdb) set print pretty on
    (gdb) p my_struct
    $1 = {
      field1 = 42,
      field2 = "hello",
      sub_struct = {
        nested_field = 3.14
      }
    }
    

    这种格式更适合阅读复杂数据结构。


2. 使用场景

  • 调试嵌套结构体
    例如,当结构体包含多层嵌套的子结构体时,缩进格式能清晰展示层级关系。

  • 查看字段较多的对象
    如果结构体有数十个字段,分行显示可以避免信息混杂。

  • 对比字段差异
    在多次打印不同对象时,整齐的格式更容易发现字段值的变化。


3. 如何启用/禁用

  • 启用漂亮打印

    (gdb) set print pretty on
    
  • 恢复默认格式

    (gdb) set print pretty off
    
  • 查看当前状态

    (gdb) show print pretty
    

    输出会显示 Pretty formatting of structures is on/off.


4. 示例对比

假设有以下C结构体:

typedef struct {
    int id;
    char name[32];
    struct { float x; float y; } position;
} Object;
  • 默认输出

    (gdb) p obj
    $1 = {id = 1, name = "test", position = {x = 10.5, y = 20.5}}
    
  • 启用set print pretty on

    (gdb) p obj
    $1 = {
      id = 1,
      name = "test",
      position = {
        x = 10.5,
        y = 20.5
      }
    }
    

5. 注意事项

  • 仅影响显示格式
    此命令仅改变输出格式,不会影响程序的实际内存或执行逻辑。

  • 临时性设置
    设置仅在当前GDB会话中有效,重启GDB后需重新启用。

  • typedef的兼容性
    如果结构体通过typedef重命名,GDB可能无法自动识别类型名。此时需手动指定类型,例如:

    (gdb) p *(original_struct_name *)ptr
    
  • 结合其他打印选项
    可以与其他打印设置结合使用,例如:

    • set print array-indexes on:显示数组索引。
    • set print elements 0:取消打印元素数量限制。
    • set print object on:显示多态对象的实际类型。

6. 高级用法:自定义Pretty Printer

如果需要更复杂的格式化(如自定义类或特定数据结构),可以通过Python编写Pretty Printer脚本,实现完全自定义的输出格式。例如,为watchface_config_t结构体编写打印机:

  1. 创建Python脚本 my_printer.py

    import gdb
    
    class WatchfaceConfigPrinter:
        def __init__(self, val):
            self.val = val
    
        def to_string(self):
            return f"watchface_config_t (theme_id={self.val['theme_id']}, ...)"
    
    def lookup_printer(val):
        if val.type.name == "watchface_config_t":
            return WatchfaceConfigPrinter(val)
        return None
    
    gdb.pretty_printers.append(lookup_printer)
    
  2. 在GDB中加载脚本

    (gdb) source my_printer.py
    
  3. 打印时自动应用格式

    (gdb) p config
    $2 = watchface_config_t (theme_id=4042322160, ...)
    

总结

  • 核心命令set print pretty on 用于格式化结构体/联合体的输出。
  • 适用场景:调试嵌套结构、多字段对象或需要清晰对比字段值的场景。
  • 扩展性:可通过Python自定义Pretty Printer实现更高级的格式化需求。

在GDB中,可以通过以下方法自动格式化变量打印,使其更易读:

1. 开启结构体漂亮打印模式

使用命令set print pretty on,这会以缩进和换行的方式显示结构体:

(gdb) set print pretty on
(gdb) p *(watchface_config_t *)0x3c4b9650

输出将变为:

$3 = {
  theme_id = 4042322160,
  pos_table_count = 4042322160,
  pos_table_index = 4042322160,
  ...
}

2. 简化指针解引用

如果config的类型已知,直接解引用即可,无需手动转换地址:

(gdb) p *config

若GDB无法自动识别类型,可能需要强制转换:

(gdb) p *(watchface_config_t *)config

3. 自定义Pretty Printer(高级)

对于复杂结构体,可编写Python脚本自定义输出格式:

  1. 创建Python脚本(如my_printers.py):
    import gdb
    
    class WatchfaceConfigPrinter:
        def __init__(self, val):
            self.val = val
    
        def to_string(self):
            return f"watchface_config_t (theme_id={self.val['theme_id']}, ...)"
    
    def lookup_type(val):
        if val.type.name == "watchface_config_t":
            return WatchfaceConfigPrinter(val)
        return None
    
    gdb.pretty_printers.append(lookup_type)
    
  2. 在GDB中加载脚本:
    (gdb) source my_printers.py
    

之后打印config时会自动应用自定义格式。

4. 检查指针有效性

异常值(如0xecececec)可能表示内存未初始化或已释放。检查指针是否有效:

(gdb) x/10x config  # 查看内存内容
(gdb) info proc mappings  # 确认地址是否在合法内存区域

5. 其他有用设置

  • set print array-indexes on:显示数组索引。
  • set print elements 0:取消打印元素数量限制。
  • set print object on:显示多态类型的实际类型。

总结步骤

  1. 开启漂亮打印
    (gdb) set print pretty on
    
  2. 直接解引用打印
    (gdb) p *config
    
  3. 若类型不明确,强制转换
    (gdb) p *(watchface_config_t *)config
    

注意:若字段值异常(如大整数、重复的魔数),需检查程序逻辑确认内存是否正确初始化,避免悬垂指针或内存越界问题。

你可能感兴趣的:(我的博客,linux,gdb)