使用GDB调试C++,如何查看已跳过函数的返回值?
GDB跳过函数后查看结构化返回值的方法
示例代码
#include <string> std::string foo() { return "bar"; } int main() { foo(); return 0; }
问题场景
当调用foo这类函数并使用next命令直接跳过执行后,无法再通过finish命令查看返回值。对于std::string这类结构化返回值,直接查看Intel x64架构的$rax寄存器只能得到指针,且不想通过C++的mangled类型名强制转换指针,导致无法让GDB漂亮打印底层的结构化值。目前临时方案是改用step进入函数后再用finish退出,GDB会自动漂亮打印返回值,但需要更正规的实现方式,或通过Python/Scheme宏实现一键打印。
解决方法
1. 无需脚本的手动方法
在跳过函数执行后,先执行info frame命令,查看当前栈帧的返回类型(输出中会包含Return value: <类型>的信息),比如对于foo函数会显示Return value: std::string。
随后直接执行以下命令打印返回值:
print *(std::string*)$rax
GDB支持直接使用非mangled的C++类型名(前提是程序编译时带完整调试信息,比如-g参数),无需手动输入mangled名称。
2. Python脚本自动化实现
通过GDB的Python API可以实现一键打印返回值的功能,无需手动输入类型:
创建脚本文件print_ret.py,内容如下:
import gdb class PrintReturnValue(gdb.Command): def __init__(self): super().__init__("print-ret", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): frame = gdb.selected_frame() return_type = frame.function.type.return_type expr = f"*({return_type.name}*)$rax" try: val = gdb.parse_and_eval(expr) print(val) except Exception as e: print(f"打印失败: {e}") PrintReturnValue()
在GDB中加载脚本:
source print_ret.py
之后只需执行print-ret命令,即可自动识别当前栈帧的返回类型,转换$rax指针并漂亮打印返回值,适配标量和结构化类型。
3. 进阶:自动记录返回值(可选)
如果需要每次执行next后自动保存返回值,可以扩展上述脚本,监听GDB的stop事件,在每次停止时自动记录返回值,但日常使用中print-ret命令已足够便捷。
内容的提问来源于stack exchange,提问作者Matej Kosik
相关产品推荐
相关产品推荐

