You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GDB分析core dump时如何查看Python扩展中NamedTuple对象属性

问题场景

假设定义了如下Python类:

class RawMessage(NamedTuple):
    data: Dict
    timestamp: float
    ...

该类的data字段为字典类型,其键和值大概率均为整数,但无法对此作出绝对确定的判断。
当前持有一份core dump核心转储文件,无关联的活动运行进程,在GDB中执行py-locals命令可查看到如下局部变量信息:

(gdb) py-locals
...
msg = <RawMessage at remote 0x7fc91ea90ee0>
...

目前仅能获取到msg对象的内存地址,无法查看对象内部实际存储的内容,期望实现与Python环境中执行print(msg.data)等效的效果,直接读取消息内容,但当前仅能使用GDB进行操作,无可用的活跃Python运行环境。
已尝试执行如下命令,均未生效:

(gdb) py-print msg.data
'msg.data' not found
(gdb) set $rawmessage = (PyObject*)0x7fc91ea90ee0
(gdb) p $rawmessage->data
There is no member named data.
(gdb) py msg
Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'msg' is not defined
Error while executing Python code.

需要找到访问该对象内部信息的方式,优先支持运行简单Python代码查看内容的方案。

解决方案

之前命令失效的核心原因有两个:一是py-locals输出的变量仅为调试扩展的打印结果,不会自动注入到py命令的执行上下文;二是NamedTuple本质是Python层面的tuple子类,C层的PyObject结构体没有对应命名字段的成员,直接强转后取成员必然失败。
可通过以下两种方式实现读取:

方法1:通过GDB Python API构造对象代理(支持执行任意Python代码)

cpython的GDB调试扩展自带内存地址到Python对象代理的转换能力,不需要依赖活跃Python进程,操作步骤如下:

  1. 确认py-locals能正常输出即代表cpython调试扩展已加载,无需额外操作
  2. 优先在当前栈帧直接读取变量,执行如下命令:
(gdb) py
# 读取当前栈帧的msg变量
msg = gdb.selected_frame().read_var("msg")
# 等价于原生Python环境下print(msg.data)
print("msg.data内容:", msg['data'])
# 读取timestamp可直接取msg['timestamp']
# 支持遍历字典所有键值
for k, v in msg['data'].items():
    print(f"键:{k}, 值:{v}")
end

如果栈帧切换导致read_var读取失败,直接用已知内存地址构造对象即可:

(gdb) py
msg_addr = 0x7fc91ea90ee0
# 将地址强转为PyObject指针,调试扩展会自动识别为Python对象代理
msg = gdb.Value(msg_addr).cast(gdb.lookup_type("PyObject").pointer()).dereference()
# NamedTuple字段按定义顺序存在tuple存储区,索引0对应data,索引1对应timestamp
data_dict = msg[0]
print("data字段内容:", data_dict)
end

方法2:纯GDB命令手动解析内存结构(无Python扩展适配时使用)

NamedTuple的C层存储结构和普通tuple完全一致,元组元素存在结构体尾部的柔性数组中,可直接读取内存:

  1. 先将对象地址强转为PyTupleObject指针,结构体内部的ob_item是指向元素指针数组的首地址,数组顺序和NamedTuple定义的字段顺序完全一致
  2. 执行如下命令读取data字段:
# 强转为PyTupleObject类型指针
(gdb) set $msg = (PyTupleObject*)0x7fc91ea90ee0
# 取数组第一个元素,即为data字段对应的PyDictObject指针
(gdb) set $data = (PyDictObject*)$msg->ob_item[0]
# 调用扩展命令打印字典内容
(gdb) py-print $data

注意:如果GDB提示找不到PyTupleObject/PyDictObject类型,说明当前core dump对应的Python调试符号未加载,先安装对应版本的Python debug符号包即可。

内容的提问来源于stack exchange,提问作者awy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:03:18