如何避免gdb调试C++程序时因循环引用触发栈溢出错误
解决方法
该问题本质是GDB自带的C++ STL美化打印器(pretty printer)遇到循环引用结构时,会无限制递归解析字段,最终触发栈溢出报错,以下是几种可用的解决方案:
方案1:临时限制打印递归深度(最快生效)
直接在GDB命令行执行以下命令,限制变量打印的最大递归深度即可:
set print max-depth 2
这个配置会让GDB展开变量最多2层就停止,再打印second_foo就不会出现递归溢出了。如果要永久生效,可以把这条命令添加到用户目录下的.gdbinit文件中,每次启动GDB都会自动加载。
方案2:自定义Foo类型的打印规则(永久解决)
可以给GDB写一个简单的Python美化打印脚本,指定Foo类型只打印index字段,不展开storage_link字段,从根源避免递归:
- 新建一个
gdb_pretty_print.py文件,写入以下内容:
import gdb.printing class FooPrinter: def __init__(self, val): self.val = val def to_string(self): return f"Foo(index={self.val['index']}, storage_link=<not expanded>)" def build_pretty_printer(): pp = gdb.printing.RegexpCollectionPrettyPrinter("my_printers") pp.add_printer('Foo', '^Foo$', FooPrinter) return pp gdb.printing.register_pretty_printer(gdb.current_objfile(), build_pretty_printer())
- 在GDB中加载该脚本:
source /path/to/gdb_pretty_print.py
之后所有Foo类型的变量打印都会按指定格式输出,不会再解析storage_link触发递归。同样可以把source命令添加到.gdbinit实现自动加载。
方案3:CLion内直接配置
如果在CLion中调试,不需要改GDB配置也可以解决:
- 调试停在断点处时,在变量面板找到任意Foo类型变量
- 右键选择「自定义数据视图」→「编辑类型渲染器」
- 给
Foo类型添加渲染规则,指定显示内容为Foo(index=$index, storage_link=$storage_link),取消勾选「递归展开子成员」即可。
内容的提问来源于stack exchange,提问作者samox
相关产品推荐
相关产品推荐

