死锁问题分析的利器——valgrind的DRD和Helgrind

c++ 内存泄漏、死锁之valgrind定位问题 本文就是抛砖引玉,希望你能够更好的使用valgrind,它能够帮你解决很多问题。 阅读详情

        在《DllMain中不当操作导致死锁问题的分析--死锁介绍》一文中,我们介绍了死锁产生的原因。一般来说,如果我们对线程同步技术掌握不牢,或者同步方案混乱,极容易导致死锁。本文我们将介绍如何使用valgrind排查死锁问题。(转载请指明出于breaksoftware的csdn博客)

        构造一个场景

#include <pthread.h>

pthread_mutex_t s_mutex_a;
pthread_mutex_t s_mutex_b;
pthread_barrier_t s_barrier;

void lock() {
    pthread_mutex_lock(&s_mutex_b);
    {
        pthread_barrier_wait(&s_barrier);

        pthread_mutex_lock(&s_mutex_a);
        pthread_mutex_unlock(&s_mutex_a);
    }
    pthread_mutex_unlock(&s_mutex_b);
}

static void* thread_routine(void* arg) {
    pthread_mutex_lock(&s_mutex_a);
    {
        pthread_barrier_wait(&s_barrier);

        pthread_mutex_lock(&s_mutex_b);
        pthread_mutex_unlock(&s_mutex_b);
    }
    pthread_mutex_unlock(&s_mutex_a);
}

int main(int argc, char** argv) {
    pthread_t tid;

    pthread_mutex_init(&s_mutex_a, 0);
    pthread_mutex_init(&s_mutex_b, 0);
    pthread_barrier_init(&s_barrier, 0, 2);

    pthread_create(&tid, 0, &thread_routine, 0);

    lock();

    pthread_join(tid, 0);
    pthread_cancel(tid);

    pthread_barrier_destroy(&s_barrier);
    pthread_mutex_destroy(&s_mutex_a);
    pthread_mutex_destroy(&s_mutex_b);

    return 0;
}

        这段代码我们只要关注lock和thread_routine两个方法。

        lock方法在主线程中执行,它先给s_mutex_b上锁,然后通过屏障s_barrier等待线程也执行到屏障处(第21行)。

        thread_routine是线程函数,它先给s_mutex_a上锁,然后通过屏障s_barrier等待主线程也执行到屏障处(第10行)。

        主线程和子线程都执行到屏障处后,屏障被打开,它们继续向下执行:主线程执行到第12行试图获取s_mutex_a;子线程执行到第23行试图获取s_mutex_b。由于这两个互斥量已经被占用,所以产生死锁。

        这是通过代码分析出来的,但是对于比较大的工程项目,我们则需要通过工具来分析。下面我们使用valgrind来分析

valgrind --tool=drd --trace-mutex=yes ./dead_lock

        我们使用上面指令,让valgrind把互斥量相关的信息给打印出来

==4749== [1] mutex_init      mutex 0x30a040
==4749== [1] mutex_init      mutex 0x30a0a0
==4749== [1] mutex_init      mutex 0x1ffefffe10
==4749== [1] mutex_ignore_ordering mutex 0x1ffefffe10
==4749== [1] mutex_trylock   mutex 0x1ffefffe10 rc 0 owner 0
==4749== [1] post_mutex_lock mutex 0x1ffefffe10 rc 0 owner 0
==4749== [1] mutex_unlock    mutex 0x1ffefffe10 rc 1
==4749== [2] mutex_trylock   mutex 0x1ffefffe10 rc 0 owner 1
==4749== [2] post_mutex_lock mutex 0x1ffefffe10 rc 0 owner 1
==4749== [2] mutex_unlock    mutex 0x1ffefffe10 rc 1
==4749== [2] mutex_trylock   mutex 0x30a040 rc 0 owner 0
==4749== [2] post_mutex_lock mutex 0x30a040 rc 0 owner 0
==4749== [1] cond_post_wait  mutex 0x1ffefffe10 rc 0 owner 2
==4749== [1] mutex_unlock    mutex 0x1ffefffe10 rc 1
==4749== [1] mutex_destroy   mutex 0x1ffefffe10 rc 0 owner 1
==4749== [1] mutex_trylock   mutex 0x30a0a0 rc 0 owner 0
==4749== [1] post_mutex_lock mutex 0x30a0a0 rc 0 owner 0
==4749== [1] mutex_trylock   mutex 0x30a040 rc 1 owner 2
==4749== [2] mutex_trylock   mutex 0x30a0a0 rc 1 owner 1

        第18行显示线程1试图给0x30a040互斥量上锁,但是该互斥量的所有者(owner)是线程2。

        第19行显示线程2试图给0x30a0a0互斥量上锁,但是该互斥量的所有者(owner)是线程1。

        如此我们便可以确定这段程序卡住是因为死锁导致的。

        但是DRD有个问题,不能指出发生死锁的位置。这个时候Helgrind该出场了。

valgrind --tool=helgrind ./dead_lock 

        helgrind执行时,如果发生死锁,需要ctrl+C来终止运行,于是可以得到如下结果

==5373== Process terminating with default action of signal 2 (SIGINT)
==5373==    at 0x4E5310D: __lll_lock_wait (lowlevellock.S:135)
==5373==    by 0x4E4C022: pthread_mutex_lock (pthread_mutex_lock.c:78)
==5373==    by 0x4C33FD6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5373==    by 0x108A11: lock (dead_lock.c:12)
==5373==    by 0x108AF4: main (dead_lock.c:38)
==5373== ---Thread-Announcement------------------------------------------
==5373== 
==5373== Thread #2 was created
==5373==    at 0x518287E: clone (clone.S:71)
==5373==    by 0x4E49EC4: create_thread (createthread.c:100)
==5373==    by 0x4E49EC4: pthread_create@@GLIBC_2.2.5 (pthread_create.c:797)
==5373==    by 0x4C36A27: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5373==    by 0x108AEA: main (dead_lock.c:36)
==5373== 
==5373== ----------------------------------------------------------------
==5373== 
==5373== Thread #2: Exiting thread still holds 1 lock
==5373==    at 0x4E5310D: __lll_lock_wait (lowlevellock.S:135)
==5373==    by 0x4E4C022: pthread_mutex_lock (pthread_mutex_lock.c:78)
==5373==    by 0x4C33FD6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5373==    by 0x108A5C: thread_routine (dead_lock.c:23)
==5373==    by 0x4C36C26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5373==    by 0x4E496DA: start_thread (pthread_create.c:463)
==5373==    by 0x518288E: clone (clone.S:95)
==5373== 
==5373== ---Thread-Announcement------------------------------------------
==5373== 
==5373== Thread #1 is the program's root thread
==5373== 
==5373== ----------------------------------------------------------------
==5373== 
==5373== Thread #1: Exiting thread still holds 1 lock
==5373==    at 0x4E5310D: __lll_lock_wait (lowlevellock.S:135)
==5373==    by 0x4E4C022: pthread_mutex_lock (pthread_mutex_lock.c:78)
==5373==    by 0x4C33FD6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5373==    by 0x108A11: lock (dead_lock.c:12)
==5373==    by 0x108AF4: main (dead_lock.c:38)

        第22和37行分别显示子线程和主线程在中断之前,都锁在哪行,这样就更容易定位问题了。

【linux】Valgrind工具集详解(十三):DRD(线程错误检测器) 用于检测多线程C和C ++程序中的错误 阅读详情

相关推荐

valgrind 分析死锁

【1】里面的1 表示owner,从上面的打印可以看到mutex 2和 3和owner形成了相互等待的过程,所以造成了死锁。运行后死锁后ctrl+c发送退出信号退出进程。2,代码pthread.c。

陌上花开缓缓归以的博客 334

互斥量、读写锁长占时分析的利器——valgrind的DRD

在进行多线程编程时,我们可能会存在同时操作(读、写)同一份内存的可能性。为了保证数据的正确性,我们往往会使用互斥量、读写锁等同步方法。(转载请指明出于breaksoftware的csdn博客) 互斥量的用法如下 pthread_mutex_lock(&amp;mutex); // do something pthread_mutex_unlock(...

方亮的专栏 1382

使用Valgrind检查并发问题

Valgrind是一个开源的内存调试、内存泄漏检测和性能分析工具。它可以帮助我们检测并发问题,包括数据竞争和死锁。

夏天的狂风的专栏 512

Valgrind 并发调试 :DRD 实战——死锁与锁序一网打尽

本文摘要: 《Valgrind并发调试·Part 2》深入解析DRD工具检测死锁与锁序问题的实战方法。通过最小可复现代码示例,演示两线程因相反加锁顺序导致的偶发死锁现象,并利用同步栅栏强制暴露问题。DRD能有效统计锁冲突密度,帮助定位临界区问题。文章提出两种标准修复方案:统一加锁顺序(首选)和trylock+退避重试机制,并给出验证命令。该教程来自嵌入式专家Jerry,配套书籍和B站视频可供拓展学习。(149字) 关键词: Valgrind、DRD、死锁检测、锁顺序反转、嵌入式调试、并发编程、线程安全

Interview_TC的博客 1384

C++ `Valgrind Helgrind` / `DRD`:检测线程错误与数据竞争

然而,一旦你手忙脚乱,忘记了同步,比如在肉还没炖熟的时候就加入酱汁,或者在切菜板还没清理干净的时候就开始切水果,最终的菜肴就会变得一团糟。它们就像线程安全的卫士,时刻守护着你的代码,帮助你揪出那些隐藏在并发代码中的捣蛋鬼,确保你的程序稳定、可靠地运行。DRD 就像一个数据竞争的猎人,它时刻追踪着程序中内存的访问情况,一旦发现有多个线程同时访问同一块内存,并且至少有一个线程在进行写操作,就会毫不犹豫地发出警告。这些问题不仅难以调试,而且往往只在特定的条件下才会出现,给程序的稳定性和可靠性带来极大的威胁。

weixin_41455464的博客 335

防火墙断网后Adobe软件还弹窗“THIS APP HAS BEEN DISABLED”?原来是科学上网导致的问题!用这个简单方法一键解决!

很多小伙伴在使用上网工具的时候时,突然遇到Adobe弹出“THIS APP HAS BEEN DISABLED”的烦人提示,这个非正版弹窗真的让人头疼!即使你之前尝试过,有时也不奏效,究其原因,原来是因为你使用了代理网络,这时Adobe的流量并不是走本地,而是走代理,导致防火墙的拦截无效。不用慌!今天我来教大家如何通过上网工具,轻松禁用Adobe验证的联网流量,彻底解决这个问题!

qq_34093397的博客 3万+

Valgrind 并发调试 :DRD 实战—死锁与锁序一网打尽

摘要:本文通过最小可复现代码示例,讲解如何使用Valgrind的DRD工具检测并发程序中的死锁与锁顺序问题。重点包括:1)DRD轻量级特性及适用场景;2)互斥量、死锁四要素等核心概念;3)构造必现死锁的同步栅栏技巧;4)两种标准修复方案——统一加锁顺序和trylock退避策略。通过实际代码演示和DRD命令输出分析,帮助开发者系统掌握并发缺陷的检测与修复方法。 (字数:148)

Interview_TC的博客 933

库卡机器人外部轴配置全流程:从接线到WorkVisual 6.0实战(附避坑指南)

本文详细解析了库卡机器人外部轴配置的全流程,涵盖从硬件接线到WorkVisual 6.0软件配置的实战步骤。重点介绍了KPP驱动模块连接、电机参数匹配、安全配置激活及零点标定等关键环节,并提供了实用的避坑指南,旨在帮助工程师高效、安全地完成外部轴集成,提升工作站柔性。

weixin_29161785的博客 496

C++多线程调试利器:Helgrind与DRD实战指南

在多线程编程中,数据竞争和死锁是两大核心挑战,它们源于多个线程对共享资源的无序访问。数据竞争发生在多个线程未同步地读写同一内存区域,导致未定义行为;而死锁则因线程间循环等待锁资源而引发程序停滞。这些并发问题的隐蔽性强,难以通过传统调试工具复现和定位。Valgrind框架下的Helgrind和DRD工具,通过运行时动态插桩技术,能够精准检测数据竞争、锁顺序错误等线程同步问题,为C++多线程程序的稳定性和正确性提供了关键保障。在开发实践中,合理运用这些工具,结合原子操作与互斥锁等同步机制,能有效提升高并发场景下

weixin_34060299的博客 398

西门子1500 PLC与巴鲁夫RFID实战:从硬件接线到数据读写的完整流程

本文详细介绍了西门子S7-1500 PLC与巴鲁夫RFID系统集成的完整实战流程。内容涵盖从硬件选型、接线、PROFINET网络配置,到在TIA Portal中安装GSD文件、组态设备、分配地址,再到使用标准功能块(如FB31)进行程序架构设计、实现数据读写以及错误诊断。文章重点分享了硬件连接要点、软件配置步骤、数据块管理技巧以及调试中常见问题的解决方案,为工业自动化工程师实施RFID项目提供了清晰的指导。

weixin_29161785的博客 386

Python爬虫实战:携程旅游攻略爬取全流程解析(动态接口+反爬破解+异步爬取)

本文介绍了携程旅游攻略的爬取全流程,涵盖静态和动态页面抓取、异步请求、高级反爬策略以及数据存储和简单分析。增加用户评论和评分抓取结合NLP分析攻略文本情感与关键词建立旅游推荐系统自动化代理IP池和验证码识别模块。

2201_76125261的博客 2039

Linux下死锁问题的排查方法

一、什么是死锁 死锁(DeadLock)是指两个或者两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程(线程)称为死锁进程(线程)。由于资源占用是互斥的,当某个进程提出申请后,使得有关进程(线程)在无外力协助下,永远分配不到必需的资源而无法继续进行,这就产生了一种特殊现象——死锁。 一种交叉持锁死锁的情形,此时执行程序中两个或多个线程发生永久堵塞(等待),每个线程都在等待被其他线程

fengruoying93的专栏 5258

STM32cubeMX配置FreeRTOS软件定时器

文章目录前言1.软件定时器概述一.软件定时器特性二、使用cubeMX生成软件定时器总结 前言 本文主要带大家了解什么是软件定时器,并且带大家使用cubeMX配置软件定时器。 1.软件定时器概述 一.软件定时器特性 软件定时器就是一个闹钟当时间到了就执行相对应的任务或者代码。软件定时器是基于系统滴答中断的。在FreeRTOS中我们可以设置无数个软件定时器。 指定时间:启动定时器和运行回调函数,两者的间隔被称为定时器的周期 (period)。 指定类型定时器有两种类型: 1.一次性 这类定时器启动后,它的回调函

m0_49476241的博客 6949

Valgrind 并发调试 :用 Helgrind 抓住线程里的“看不见的错”

本文介绍了Valgrind工具集中的Helgrind线程错误检测器,用于发现多线程程序中的并发问题。通过一个计数器竞态的最小示例,演示了如何用Helgrind检测数据竞争,并给出互斥锁和原子操作两种解决方案。文章还对比了Helgrind与DRD的特点,建议先用Helgrind清理基础并发错误,再用DRD检测死锁。最后提供了实用的并发调试清单,包括编译选项、修复优先级和持续集成建议。帮助开发者可视化"看不见的"并发错误,提高多线程代码质量。

Interview_TC的博客 1021

PSM倾向性评分分析介绍、spss进行倾向性评分分析示例

PSM倾向性评分分析介绍、spss进行倾向性评分分析示例

statistics+insight+vista+power 1481

YOLOv8改进 | 注意力篇 | YOLOv8引入EMAttention(EMA)注意力

具体来说,除了对全局信息进行编码以重新校准每个并行分支中的通道权重之外,还通过跨维度交互来进一步聚合两个并行分支的输出特征,以捕获像素级的成对关系。3. 跨空间学习:除了在每个并行子网络中建立局部的跨通道交互外,EMA模块还通过跨空间学习方法融合了两个并行子网络的输出特征图。到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

tsg6698的博客 896

Valgrind 并发调试 ·:用 Helgrind 抓住线程里的“看不见的错”

本文介绍了Valgrind工具集中的Helgrind线程错误检测器,通过最小示例演示如何检测多线程程序中的并发错误。文章首先展示了一个存在数据竞争(Data Race)的代码示例,该程序在多线程环境下未加锁地修改共享变量,虽然运行结果看似正确,但存在潜在问题。随后分别给出使用互斥锁和原子操作两种修复方案,并通过Helgrind验证修复效果。文章还对比了Helgrind与DRD工具的特点,建议先用Helgrind检测数据竞争和锁误用,再用DRD检查死锁。最后提供了快速上手清单,包括编译选项、运行命令和修复优先

Interview_TC的博客 1072

【YOLO】YOLOV5-Seg的Segment模块解析

Segment模块同时输出检测结果和分割掩模,通过轻量级分割头实现实时实例分割

浩瀚之水的专栏 599

C++线程异常检测工具(Valrind之helgrind和DRD)

从日志中,也可以找到相应的锁的签名,看到其对应的关系和顺序。在平常工作生活中,可以借助检测结果,可以快速的发现,可能存在死锁风险问题。因此,通过查看每个锁占用的时间,根据自己的业务逻辑需要进行判定是否可以减小锁的范围,减小独占时间,提高并发性。只能检测某一个锁占用的时间,不能统计多处、多个锁的占用时间。一般程序退出时,都会解锁,但是在程序退出时,仍然持有锁,说明此处发生死锁了。此工具可支持检测:多线程接口使用问题、竞态问题、锁范围问题。首先将应用程序,编译多线程场景下的可执行程序,需要链接。

youngzhiyong的博客 1093

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Linux Mutex机制与死锁分析

在Linux系统上,Mutex机制相比于信号量,实现更加简单和高效,但使用也更加严格 1. 任何时刻只有一个任务可以持有Mutex 2. 谁上锁谁解锁 3. 不允许递归地上锁和解锁 4. 当进程持有一个Mutex时,不允许退出 5. Mutex只能通过相关API来管理,不可被拷贝,手动初始化或重复初始化 在应用层来说,一般Mutex多用于多线程间的同步,本文针对第四点"当进程持有一个Mutex时,不允许退出"来做一些探讨和测试 关于多进程使用Mutex,有一个很经典的场景,即共享内存通讯 两

一个带你入门的嵌入式开发“老者” 3490

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

进程、线程死锁和内存泄漏检测工具-Valgrind

死锁检测工具vargrind包含DRD和Helgrind检测工具。

荒野 664

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

V 语言线程安全实战指南:从 Mutex 回调队列、原子计数器到 Valgrind 数据竞争检测

本文以 V 语言仓库中的 [thread_safety 示例集](https://link.gitcode.com/i/d0970b9e56ab619cfab0a80a2c2b8ee0) 为主线,完整讲解多线程场景下三类最经典的线程安全手段:**互斥锁保护共享队列**、**原子操作** 与 **`shared` + `lock`/`rlock` 同步**。读完本文,你将掌握对应示例的编译运行方式、

gitblog_00792的博客 1152

多线程调试技巧:GDB与Valgrind解决Linux竞态条件、死锁问题

多线程调试是Linux开发中的关键技能,面对并发程序中的竞态条件和死锁问题,掌握有效的调试方法能显著提升开发效率。本文将分享几个实用的调试技巧,帮助开发者快速定位和解决多线程问题。

2509_93883384的博客 191

深入解析Valgrind:从内存泄漏检测到性能剖析的完整指南

在C/C++等系统级编程中,内存管理和并发问题是开发过程中的核心挑战。内存泄漏、野指针、数据竞争等错误往往难以复现和定位,直接影响程序的稳定性和性能。Valgrind作为一套动态分析工具框架,通过模拟程序执行环境,深入检测内存使用错误、线程同步问题及缓存性能瓶颈。其核心工具Memcheck利用V-bit和A-bit机制追踪内存状态,能精准定位未初始化值使用、非法内存访问及内存泄漏;Helgrind和DRD则基于锁集算法分析数据竞争与死锁;Cachegrind和Massif分别从硬件缓存和堆内存使用角度提供性

weixin_34345753的博客 668

Valgrind 核心工具全解析:从内存检测到多线程调试实战指南

在 C/C++ 开发中,内存管理与多线程并发是两大核心挑战,内存泄漏、数据竞争等问题往往难以通过常规调试手段发现。动态二进制插桩技术通过在程序运行时监控其指令执行与内存操作,为这类深层次问题提供了强大的检测能力。Valgrind 正是基于此原理构建的程序分析框架,其技术价值在于能够以‘上帝视角’对内存读写、堆分配释放及线程同步进行严密监控,从而精准定位常规测试难以覆盖的缺陷。在应用场景上,它尤其适用于系统底层、高性能计算、嵌入式及长期运行的后台服务等对稳定性和健壮性要求极高的领域。本文以 Valgrind

weixin_34356555的博客 402

Valgrind工具链深度解析:从内存检测到性能剖析的C/C++开发实战指南

在C/C++开发中,内存管理和性能优化是保障程序稳定与高效运行的核心挑战。其原理在于程序运行时对内存的动态分配与释放、多线程并发访问以及CPU缓存利用等底层机制。这些机制若处理不当,会导致内存泄漏、数据竞争和性能瓶颈,严重影响软件质量与系统稳定性。Valgrind作为一套强大的动态分析工具集,通过虚拟执行环境插入检测代码,为开发者提供了透视程序运行时行为的独特能力。其技术价值在于能够精准定位传统调试器难以发现的深层错误,如使用未初始化的内存、缓冲区溢出等,并能剖析缓存命中率与函数调用热点。在应用场景上,它广

weixin_30756499的博客 364
上一篇: 互斥量、读写锁长占时分析的利器——valgrind的DRD
下一篇: 数据竞争(data race)问题分析的利器——valgrind的Helgrind
breaksoftware
breaksoftware 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄20年 6901粉丝 724原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

breaksoftware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值