0

0

如何使用rr进行c++程序的时间旅行调试? (复现非确定性BUG)

穿越時空

穿越時空

发布时间:2026-01-13 11:43:02

|

903人浏览过

|

来源于php中文网

原创

rr 是一个 Linux x86_64 平台的确定性记录与回放调试工具,通过完整捕获系统调用、信号、线程调度和内存访问,实现 100% 可复现的时间旅行调试,专治多线程竞争、内存乱序等非确定性 BUG。

如何使用rr进行c++程序的时间旅行调试? (复现非确定性bug)

什么是 rr,它为什么能抓到非确定性 BUG

rr 不是普通调试器,而是一个「确定性记录与回放」工具。它把程序执行时的所有系统调用、信号、线程调度、内存访问(通过硬件断点/ptrace 拦截)完整记录下来,生成一个 trace 目录。之后无论重放多少次,执行路径都完全一致——这才是时间旅行调试的基础。

对 C++ 程序尤其有用:多线程竞争、内存乱序、未初始化变量、std::thread / std::async 启动时机差异导致的偶发崩溃或逻辑错误,在 rr 下变成 100% 可复现、可单步、可倒退的问题。

注意:rr 仅支持 Linux x86_64(要求 CPU 支持 Intel PT 或使用软件回溯模式),不支持 macOS / Windows;且需关闭 ASLR(echo 0 | sudo tee /proc/sys/kernel/randomize_va_space)才能保证地址空间稳定。

编译和运行 C++ 程序时必须加的参数

rr 对二进制无侵入,但调试体验严重依赖符号和优化控制。不加这些,你会遇到:断点打不到、变量显示为 帧跳变、甚至 rr 自身报 unhandled ptrace event

立即学习C++免费学习笔记(深入)”;

  • 编译必须带 -g(生成 DWARF 调试信息),否则 rr 回放时 gdb 无法映射源码
  • 推荐用 -O0-O1-O2 及以上常导致变量生命周期被优化掉,倒退时无法读值
  • 避免 -fomit-frame-pointer(现代 GCC 默认不开,但若项目显式加了,需去掉)——rr 依赖帧指针做栈回溯
  • 链接时无需特殊操作;静态链接 libc 不被 rr 支持,务必用动态链接

示例编译命令:

g++ -g -O0 -pthread main.cpp -o myapp

然后用 rr record 启动:

绘蛙-多图成片
绘蛙-多图成片

绘蛙新推出的AI图生视频工具

下载
rr record ./myapp

运行结束后会输出类似 rr recorded traceid 1234 的提示。

在 gdb 中倒退执行、设条件断点、检查竞态点

rr 自带 patched 版本的 gdb(通常叫 rr replay),它扩展了 reverse-stepreverse-continuewatch -l 等指令。不要用系统自带 gdb 打开 trace。

  • 启动回放:rr replay(自动加载最新 trace)或指定 trace:rr replay 1234
  • 倒退执行:reverse-step(反向单步)、reverse-next(反向跳过函数)、reverse-continue(反向运行到上一个断点)
  • 监控某变量被谁修改:watch -l my_var-l 表示 location watchpoint,rr 会自动在写该内存的所有位置下断点)
  • 只在特定线程触发断点:thread 3; break MyClass::handle(),再配合 reverse-continue 快速定位该线程出问题前的状态
  • 查看所有线程调度事件:info threads + thread apply all bt,rr 的线程 ID 和 trace 中的 kernel TID 一一对应,不会混淆

典型竞态复现流程:先用 rr replay 运行至 crash,bt 看栈;然后 reverse-continue 回退到 segfault 前几秒;再对疑似共享变量加 watch -lc 一次就停在最后一次写入它的代码行——往往就是那个漏锁的 push_back 或未同步的 flag 修改。

常见失败原因和绕过方法

rr 不是银弹。以下情况会导致 record 失败或 replay 行为异常,不是你用错了,而是底层机制限制:

  • rr: fatal error: Unsupported system call: 431(如某些新内核的 pidfd_getfd)→ 升级 rr 到 v5.8+,或临时降级内核
  • 程序用了 mmap(MAP_SYNC)、GPU ioctl、eBPF 加载等 rr 未覆盖的系统调用 → 在 rr record 后加 --disable-syscall-logging=xxx 屏蔽(但可能丢失部分确定性)
  • 程序 fork 出子进程且子进程长期存活(如守护进程)→ rr 默认只记录主进程树,加 --preserve-files 并确保子进程不脱离 session
  • 使用了 std::random_device(从 /dev/urandom 读)→ rr 会记录其返回值,但若程序依赖真随机性做分支,回放时行为仍确定;如需模拟不同种子,改用 std::mt19937 + 固定 seed

最易被忽略的一点:rr 的「时间旅行」只作用于当前 trace 内存和寄存器状态,不包括外部文件、网络响应、共享内存段(除非由被记录进程创建并管理)。如果 BUG 依赖某个第三方服务返回的特定 JSON 字段,得先 mock 它——rr 解决不了外部不确定性,只解决「程序自身并发不确定性」。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

411

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

532

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

309

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

307

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

732

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

187

2023.10.18

nginx部署php项目教程汇总
nginx部署php项目教程汇总

本专题整合了nginx部署php项目教程汇总,阅读专题下面的文章了解更多详细内容。

1

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7万人学习

Git 教程
Git 教程

共21课时 | 2.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号