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

如何转储C++程序执行流程、控制流及局部变量定位版本回归

C++版本回归定位:执行过程记录对比方案

需求背景

现有C++程序的v1与v1.01版本,v1.01引入回归问题。需要通过相同输入下的执行过程记录(包含函数调用信息、局部变量变化等),对比两个版本的行为差异来自动定位回归点。开发环境优先Windows MSVC,其次Linux Clang,倾向使用通用、跨语言工具,若工具方案受限则考虑代码插桩。

示例代码

原始待分析代码:

int test(int n) {
    n++;
    std::cout << n << std::endl;
    n += 15;
    return n + 1;
}

int main(int argc, char** argv) {
    auto result = test(std::stoi(argv[1]));
    std::cout << result << std::endl;
}

期望执行记录格式

Visited Function: main with arguments (argc: 2, argv ["path", 7])
Visited Function test with arguments (n: 7)
test: n set to 8
test: n set to 23
test: n set to 24
Exit function test
Main: result set to 24

一、Windows时间旅行调试(MSVC环境)

针对你遇到的「记录格式无法转成人类可读内容」问题,可按以下步骤操作:

1. 准备工作

编译程序时开启调试符号:在MSVC项目属性中设置C/C++ -> 常规 -> 调试信息格式为程序数据库(/Zi),确保生成PDB符号文件。

2. 生成时间旅行记录

  • 打开WinDbg,加载目标程序(v1或v1.01版本)
  • 输入命令.ttrace record开始执行记录
  • 运行程序并传入相同测试参数(如7),待程序执行完成后输入.ttrace stop保存记录

3. 导出可读执行记录

  • 回放记录:输入.ttrace replay加载之前保存的记录
  • 配置日志输出:输入.logopen output_v1.txt,将所有调试输出写入文件
  • 跟踪函数与变量:
    • 在函数入口/出口设置断点:bp test、bp main
    • 函数断点触发时,用dx @$curstack查看调用栈与参数,用dx n查看变量当前值
    • 用watch n设置变量监视,每次变量修改时自动触发日志
    • 用p(单步过函数)或t(单步进函数)遍历执行流程,日志会自动记录所有操作
  • 分别导出v1和v1.01的日志文件,直接对比文本差异即可定位回归点

二、rr调试器(Linux Clang环境)

rr是Linux下的轻量级时间旅行调试工具,适合精准对比执行轨迹:

1. 编译程序

用Clang编译时带上调试符号:

clang++ -g test.cpp -o test

2. 记录执行过程

rr record ./test 7

3. 回放与导出记录

  • 启动回放:rr replay,自动进入gdb交互环境
  • 导出函数调用与变量变化:
    • 用info args查看当前函数参数
    • 用watch n监视变量修改,每次变化都会打印日志
    • 用rr dump将完整执行轨迹导出为文本文件
  • 对比v1和v1.01的dump文件,筛选变量值或函数行为不一致的节点

三、代码插桩方案(通用兼容)

若通用工具无法满足需求,可通过手动插桩直接输出符合期望的执行记录:

插桩后示例代码

#include <iostream>
#include <string>

// 记录函数入口及参数
#define LOG_FUNC_ENTRY(func_name, args_str) \
    std::cout << "Visited Function: " << func_name << " with arguments (" << args_str << ")" << std::endl

// 记录变量修改
#define LOG_VAR_CHANGE(func_name, var_name, new_val) \
    std::cout << func_name << ": " << var_name << " set to " << new_val << std::endl

int test(int n) {
    LOG_FUNC_ENTRY("test", "n: " << n);
    
    n++;
    LOG_VAR_CHANGE("test", "n", n);
    
    std::cout << n << std::endl;
    n += 15;
    LOG_VAR_CHANGE("test", "n", n);
    
    int ret = n + 1;
    LOG_VAR_CHANGE("test", "n (return value)", ret);
    std::cout << "Exit function test" << std::endl;
    return ret;
}

int main(int argc, char** argv) {
    int input = std::stoi(argv[1]);
    LOG_FUNC_ENTRY("main", "argc: " << argc << ", argv [\"" << argv[0] << "\", " << input << "]");
    
    auto result = test(input);
    LOG_VAR_CHANGE("Main", "result", result);
    std::cout << result << std::endl;
    return 0;
}

使用方式

  • 分别编译v1和v1.01的插桩版本,传入相同参数运行
  • 直接对比两个版本的控制台输出,快速定位变量变化或函数行为的差异点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:53:13