rr来debug你的C/C++程序(Linux)

2023/9/30 18:38:04

如何用rr来debug你的C/C++程序(Linux)

想象一下如果你的程序某时会崩溃,但是不能稳定复现,你会如何debug它?

用传统debugger面临的问题就是你不知道这次运行的时候能不能复现,你猜测可能某段代码出现了问题,所以进行了一番检查。但如果最后不能复现的话,刚刚所做的工作就是无用的。gdb通过一个反向调试的功能解决了这个问题。但是gdb的反向调试代价很大,在大型项目上运行很吃力。Bug出现的几率高还好,但如果出现的概率是1/100,甚至1/1000呢?

要么就用大量printf,通过print出数据来进行debug,好处是重复运行程序的成本较低,可以写个脚本,反复可以多次尝试,直到程序崩溃,然后反回去看log。但也有一样的问题就是效率不高,哪怕复现成功了,也很有可能现有的printf并不能解决问题,需要加更多的printf,又要反复运行程序来复现。

rr的出现就是来解决上面提到的问题。rr是一个debugger,通过记录程序运行时的状态,来提供一个可以反复反向调试的debug环境。

rr的优点

  • 比gdb的反向调试更成熟,并且有更少的消耗

  • 对多线程进程友好,可以只调试某个进程

  • 支持gdb的指令

安装

推荐按着官方文档来进行本地编译,然后安装。请注意rr现在只能在Linux上运行并且对CPU有一定的要求,具体要求请看官方文档。

ubuntu快速安装

cd /tmp
wget https://github.com/rr-debugger/rr/releases/download/5.5.0/rr-5.5.0-Linux-$(uname -m).deb
sudo dpkg -i rr-5.5.0-Linux-$(uname -m).deb

操作系统配置

需要 Linux 内核 3.11 或更高版本(检查uname -r)。

/proc/sys/kernel/perf_event_paranoid必须 <= 1 rr 才能有效工作(即能够使用perf计数器)。一些发行版将其设置为 2 或更高,在这种情况下,您需要将其设置为 1 或使用rr record -n,这很慢。通过运行临时更改设置

$ sudo sysctl kernel.perf_event_paranoid=1

基础使用方法

使用rr总共分成两步

  1. 第一步是rr record - 运行程序,并且记录下程序运行时的状态。

  2. 第二部是rr replay - 回放记录好的程序。

实例

  #include <cstdio>
  #include <thread>
  #include <stdlib.h>
​
  void inc(int& x, int id) {
    id = id + 1; //这一行有点多余,主要是为了展示rr的reverse-continue 功能
    if (x == 2 && id == 3) {
      abort();
    }
    ++x;
    printf("x=%d\n", x);
  }
​
  int main () {
    int x = 0;
    std::thread t1(inc, std::ref(x), 1);
    std::thread t2(inc, std::ref(x), 2);
    std::thread t3(inc, std::ref(x), 3);
    std::thread t4(inc, std::ref(x), 4);
​
    t1.join();
    t2.join();
    t3.join();
    t4.join();
  }

上面这个程序启动了多个线程,会在当t2这个线程运行时x == 2 && id == 3的时候崩溃。因为线程运行的顺序是不可控的,所以这个程序并不会总是崩溃。

我们首先编译上面这个程序

  • 运行g++ -g main.cpp -o main -lpthread。编译好后,我们得到了 main 这个二进制文件。

然后我们来record

  • 这里我们运行rr record --chaos ./main

rr record --chaos ./main
  • 正常情况我们 rr record ../main 就可以了,但我们这里用了--chaos让rr可以更加随机的进行调度,从而增加复现这个bug的概率。

  • 我们还可以自动化这个步骤通过while rr record --chaos ./main; do :; done 来反复运行这个程序,这个while循环会在main崩溃的时候自动结束。

while rr record --chaos ./main; do :; done 

我这次运行了32次才成功复现这个崩溃。

rr 会把每次的记录存放在~/.local/share/rr里面,这时候我们ls看一下。

 

每个main-<数字>就是rr存放的记录,rr支持我们回放每一个记录,rr replay 默认会回放最新的那个,我们直接rr replay就好了。

上图就是rr debugger的样子。因为rr使用的是gdb protocol,所以我们可以运行各种gdb的指令。

我们接下来利用gdb的continue指令 (continue指令会让程序一直运行,直到程序结束,程序崩溃,或者命中断点),让程序自动停在崩溃的地方。

我们看到rr的回放也print出了x=1 和 x=2, 跟当时运行时是完全一样的。这里我们输入bt可以检查call stack的内容。可以看到abort()是让程序崩溃的原因。

 

输入up 2,来到inc()的这个frame。再配合list,就可以看到具体造成崩溃的代码。这里我们输入 p id 可以看到当前id的数据,确实是id == 3造成了崩溃。

这时候我们需要寻找为什么id是3的原因,这段代码很明显是由id = id + 1造成的,但是假如我们不知道是哪里造成id变化,我们可以输入watch -l id 来观察这个变量,再通过rc来回到造成变化的代码。

注意这里我们输入了rc两次,第一次rc的时候,rr收到了程序崩溃的信号,所以停止了,我们需要再输入一次让它继续。rr自动就帮我们回到了id变化的这一行代码,这时候我们再看p idid就是2了。通过追逐id的变化,我们就可以对代码进行必要的修改了。

这就是rr的能力,不单单我们返回到了这一行代码,连程序相应的状态都回到了这个时刻。rr的强大之处就是给我们的一种回到过去的能力。

ROS下使用方式补充

调试ROS节点方式如下:

rosrun --prefix 'rr record' you_ros_node

rosrun --prefix 'rr record --chaos' teleop_twist_keyboard teleop_twist_keyboard.py

例如调试小乌龟:

➜  ~ rosrun --prefix 'rr record' turtlesim turtlesim_node 
On Zen CPUs, rr will not work reliably unless you disable the hardware SpecLockMap optimization.
For instructions on how to do this, see https://github.com/rr-debugger/rr/wiki/Zen
rr: Saving execution to trace directory `/home/efsz/.local/share/rr/turtlesim_node-1'.
[ INFO] [1668656353.548471340]: Starting turtlesim with node name /turtlesim
[ INFO] [1668656353.562282765]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

 


http://www.jnnr.cn/a/134743.html

相关文章

P3205 [HNOI2010]合唱队

[HNOI2010]合唱队 题目描述 为了在即将到来的晚会上有更好的演出效果&#xff0c;作为 AAA 合唱队负责人的小 A 需要将合唱队的人根据他们的身高排出一个队形。假定合唱队一共 nnn 个人&#xff0c;第 iii 个人的身高为 hih_ihi​ 米&#xff08;1000≤hi≤20001000 \le h_i …

C# 自定义控件

一 自定义控件 1 自定义控件的三种方式&#xff1a; 1&#xff09;复合控件&#xff1a;将标准控件组合起来 class YourControl:UserControl{}2) 扩展控件&#xff1a;继承于标准控件 class YourControl:Button{}3) 自定义控件&#xff1a;完全地自定义一个控件 class You…

超级账本Fabric的世界状态操作与账本操作

在 Hyperledger Fabric 中&#xff0c;账本由两个不同但相关的部分组成 - 世界状态和区块链。 世界状态&#xff1a; 一个数据库&#xff0c;其中存储了一组帐本状态的当前值的缓存。世界状态使程序可以轻松地直接访问状态的当前值&#xff0c;而不必通过遍历整个交易日志来计…

2022测试开发面试题大全及答案(包含测试基础|接口测试|自动化测试...)【289页】

在我认为&#xff0c;对于测试面试以及进阶的最佳学习方法莫过于刷题博客书籍视频总结&#xff0c;前几者作者将淋漓尽致地挥毫于这篇博客文章中&#xff0c;至于总结在于个人&#xff0c;实际上越到后面你会发现面试并不难&#xff0c;其次就是在刷题的过程中有没有去思考&…

RE转NFA转DFA

https://github.com/Nightmare4214/re_nfa_dfa 前置知识 ϵ\epsilonϵ代表空串 语言 某个给定字母表上一个任意的可数的串集合 正则语言/正则表达式 正则语言&#xff08;regular language&#xff09;/正则表达式&#xff08;regular expression&#xff09; 每个正则表达…

并发编程永远绕不开的难题,跟着大牛带你Java并发编程从入门到精通

我们知道&#xff0c;很多框架或者自研组件的底层&#xff0c;都或多或少涉及到并发编程方面的技术点。 比如&#xff1a;在一些本地缓存组件中&#xff0c;当本地缓存过期后&#xff0c;需要从数据库加载数据&#xff0c;这个阶段中就会涉及到线程并发请求的处理&#xff1b;在…

opencv+tensorflow手势识别+图片特效

一、效果展示 手势识别特效展示&#xff01;&#xff08;此处只录入四种&#xff0c;简单运行&#xff01;&#xff01;&#xff01;&#xff09; 二、 项目介绍 本次项目是在上一篇博文上的改进版本&#xff0c;在此次设计中录入了四种手势增加了训练图片和训练轮数&#xff…

NUMA架构详解

基本概念 为什么要有多处理器架构&#xff1f; 由于摩尔定律的失效&#xff0c;单个CPU内的晶体管的数量接近于饱和状态&#xff0c;因此单个CPU的性能已经接近饱和状态&#xff0c;这时&#xff0c;要想提高计算机的性能&#xff0c;就必须朝着多核架构发展。多核架构中&…

【Maven】使用maven profile 动态激活不同环境、依赖打包部署

使用maven profile 动态激活不同环境、依赖打包部署前言一、配置二、激活Profile三、动态依赖 示例一些其他参考&#xff1a;前言 在开发过程中&#xff0c;我们的软件会面对不同的运行环境&#xff0c;比如开发环境、测试环境、生产环境&#xff0c;而我们的软件在不同的环境中…

Centos 7下安装php+mysql+nginx+wordpress教程新版

安装zsh+oh-my-zsh 安装zsh的原因是因为不喜欢自带的ssh工具,感觉没有这个好用,我最常用的就是记忆功能,比如输入某个字母,按上下键会自动补全已经使用过的命令,安装也很简单,一条命令搞定,他的扩展也很多,这里只讲最简单的安装,当然也可以不需要安装。 执行yum inst…

tomcat官网下载配置全部详细步骤(包含各种报错解决办法)

前言&#xff1a; 名字由来&#xff1a;翻译是野猫&#xff0c;tomcat的作者初衷是希望这个软件可以自力更生&#xff0c;自给自足。不依赖其他插件&#xff0c;独立达到提供web服务的效果 1.tocat和java的关系&#xff1f; tomcat是用Java语言编写的&#xff0c;需要运行在…

每个程序员都要知道的一个网站

在日常开发过程中&#xff0c;你是不是经常回到搜索引擎&#xff0c;搜索某个功能的实现方式&#xff0c;比如&#xff1a;Javascript 数组排序、正则表达式等等。 今天给大家推荐的这个网站&#xff0c;就可以满足大家的需求&#xff0c;它叫&#xff1a;30secondsofcode&…

​ 详解Linux内核通信-proc文件系统

使用 /proc 文件系统来访问 Linux 内核的内容&#xff0c;这个虚拟文件系统 在内核空间和用户空间之间打开了一个通信窗口&#xff1a; /proc 文件系统是一个虚拟文件系统&#xff0c;通过它可以使用一种新的方法在 Linux内核空间和用户间之间进行通信。在 /proc 文件系统中&…

虚拟主播是什么,有什么技术原理?- 沉睡者IT

虚拟主播是什么&#xff1f;虚拟形象人物是通过人工智能技术的研究和积累&#xff0c;在克服了计算机图形学和AI核心技术的各个学科的智能化、平台化、虚拟人、虚拟内容在各个维度的技术难题后&#xff0c;提供给用户的核心资产。虚拟主播指的是在视频网站上使用虚拟图片进行投…

智能微型断路器的功能有哪些?和网关搭配的作用在哪?

安科瑞 华楠 ASCB1 系列智能微型断路器是安科瑞电气股份有限公司 全新推出的智慧用电产品&#xff0c;产品由智能微型断路器与智 能网关两部分组成&#xff0c;可用于对用电线路的关键电气因 素&#xff0c;如电压、电流、功率、温度、漏电、能耗等进行实 时监测&#xff0c;具…

asp.net+sqlserver个人简历生成系统C#项目

目 录 1 项目来源 1 1.1 项目背景 1 1.2目的和意义 1 1.3研究成果 2 2 系统开发环境 3 2.1 Visual Studio.NET开发平台 3 2.2 ASP.NET 2.0开发技术 3 2.3 ADO.NET数据访问技术 4 2.4 Microsoft SQL Server简介 4 2.5 B/S结构 5 3 需求分析 6…

测试工作3年还在基础岗?可能只是因为你的工作能力差

对于职场人而言&#xff0c;工作中升职加薪是每个人都梦寐以求的事情&#xff0c;但有些小伙伴表示&#xff0c;自己来到一个公司三年&#xff0c;却依旧停留在基础岗位上&#xff0c;究竟是什么原因呢&#xff1f; 其实从根本来说&#xff0c;很有可能只是因为&#xff1a;你…

Windows11更新最新系统版本后无法播放媒体声音

故障机器Dell为例 step1&#xff1a;检测系统提示音是否正常&#xff0c;正常可观察第二步&#xff1b; step2:打开计算机管理-设备管理器-观察声音设备是否正常&#xff0c;可右键编辑重启驱动 step3&#xff1a;打开无法播放媒体声音的设备查看设置&#xff0c;Firefox为例 …

使用verdaccio搭建私有组件库

前言 最近公司需要根据现有的公用组件搭建一套私有组件库&#xff0c;方便其他项目使用&#xff0c;然后经过一系列尝试和走了许多坑&#xff0c;终于搭建成功了&#xff0c;这里记录下搭建步骤&#xff0c;希望对你有些帮助。 为什么选择verdaccio 由于公司组件库越来越多&…

【Vue.js设计与实现】第4章 响应系统的作用与实现

前言&#xff1a; 本文是我看的Vue.js设计与实现这本书第二篇 响应系统 的第4章 响应系统的作用与实现的一些总结与收获。 第4章从宏观视角讲述了Vue.js 3.0中响应系统的实现机制。从副作用函数开始&#xff0c;逐步实现一个完善的响应系统&#xff0c;还讲述了计算属性和watch…
最新文章