Valgrind的多线程调试工具 
Helgrind是Valgrind的一个重点功能 本节主要针对与多线程基本安全问题进行检测:【所有的代码环境都是在POSIX_THREAD模式下】

写线程代码时 经常碰到如下问题
1)  资源不安全访问 【就是多个线程在没有同步的情况下写某个资源体】
2) 死锁问题
3)  POSIX pthreads API的错误使用
4)  在前面几个基础上都能安全无误的情况下 多于多线程程序就是要能够能好将同步块尽量缩到最小  【这是一个很大的课题】
  解决问题:
    ​问题1:   调用Helgrind能够很好的解决掉  已基本例子为例:
    ​

  1. #include <pthread.h>

  2. int var = 0;

  3. void* child_fn ( void* arg ) {

  4. var++;

  5. return NULL;

  6. }

  7. int main ( void ) {

  8. pthread_t child;

  9. pthread_t child2;

  10. pthread_create(&child,NULL, child_fn, NULL);

  11. pthread_create(&child2,NULL,child_fn,NULL);

  12. pthread_join(child,NULL);

  13. pthread_join(child2,NULL);

  14. return 0;

  15. }

明显var是共享的 不安全访问,调用Helgrind看看怎么能够检测出来
gcc -g thread_helgrind.c  -o thread_helgrind -lpthread
valgrind --tool=helgrind ./thread_helgrind 
可以看出valgrind弹出如下输出信息:

==25516== Helgrind, a thread error detector

==25516== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.

==25516== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info

==25516== Command: ./thread_helgrind

==25516==

==25516== ---Thread-Announcement------------------------------------------

==25516==

==25516== Thread #3 was created

==25516==    at 0x415B3C8: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==25516==

==25516== ---Thread-Announcement------------------------------------------

==25516==

==25516== Thread #2 was created

==25516==    at 0x415B3C8: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==25516==

==25516== ----------------------------------------------------------------

==25516==

==25516== Possible data race during read of size 4 at 0x804A028 by thread #3

==25516== Locks held: none

==25516==    at 0x804851F: child_fn (thread_helgrind.c:12)

==25516==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==25516==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==25516==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==25516==

==25516== This conflicts with a previous write of size 4 by thread #2

==25516== Locks held: none

==25516==    at 0x8048527: child_fn (thread_helgrind.c:12)

==25516==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==25516==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==25516==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==25516==

==25516== ----------------------------------------------------------------

==25516==

==25516== Possible data race during write of size 4 at 0x804A028 by thread #3

==25516== Locks held: none

==25516==    at 0x8048527: child_fn (thread_helgrind.c:12)

==25516==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==25516==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==25516==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==25516==

==25516== This conflicts with a previous write of size 4 by thread #2

==25516== Locks held: none

==25516==    at 0x8048527: child_fn (thread_helgrind.c:12)

==25516==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==25516==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==25516==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==25516==

==25516==

==25516== For counts of detected and suppressed errors, rerun with: -v

==25516== Use --history-level=approx or =none to gain increased speed, at

==25516== the cost of reduced accuracy of conflicting-access information

==25516== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

可以看出绿色就显示的data_race错误  可以直接定位到var前后没有locks/

问题2:
    ​死锁问题是尽量避免  对于helgrind可以检测出加锁解锁顺序出现问题导致的死锁问题    这个问题我们可以好好看下:
    ​首先 看下一个正常的程序
    ​

#include <pthread.h>

pthread_mutex_t mut_thread;

int var = 0;

void* child_fn ( void* arg ) {

pthread_mutex_lock(&mut_thread);

var++;

pthread_mutex_unlock(&mut_thread);

return NULL;

}

int main ( void ) {

pthread_t child;

pthread_t child2;

pthread_mutex_init(&mut_thread,NULL);

pthread_create(&child,NULL, child_fn, NULL);

pthread_create(&child2,NULL,child_fn,NULL);

pthread_join(child,NULL);

pthread_join(child2,NULL);

return 0;

}

正常加锁解锁  没有问题 
在看下连续加2次锁的情况:

#include <pthread.h>

pthread_mutex_t mut_thread;

int var = 0;

void* child_fn ( void* arg ) {

pthread_mutex_lock(&mut_thread);

var++;

pthread_mutex_lock(&mut_thread);

return NULL;

}

int main ( void ) {

pthread_t child;

pthread_t child2;

pthread_mutex_init(&mut_thread,NULL);

pthread_create(&child,NULL, child_fn, NULL);

pthread_create(&child2,NULL,child_fn,NULL);

pthread_join(child,NULL);

pthread_join(child2,NULL);

return 0;

}

看下这个helgrind打印出来的东西 【当然要杀死 不然会一直卡在那里动都不动一下】

==26534== Helgrind, a thread error detector

==26534== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.

==26534== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info

==26534== Command: ./deadlock_helgrind

==26534==

==26534== ---Thread-Announcement------------------------------------------

==26534==

==26534== Thread #2 was created

==26534==    at 0x415B3C8: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26534==

==26534== ----------------------------------------------------------------

==26534==

==26534== Thread #2: Attempt to re-lock a non-recursive lock I already hold

==26534==    at 0x402E8E5: pthread_mutex_lock (hg_intercepts.c:507)

==26534==    by 0x80485C6: child_fn (deadlock_helgrind.c:14)

==26534==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==26534==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26534==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26534==  Lock was previously acquired

==26534==    at 0x402E95D: pthread_mutex_lock (hg_intercepts.c:518)

==26534==    by 0x80485AD: child_fn (deadlock_helgrind.c:12)

==26534==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==26534==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26534==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26534==

^C==26534== ----------------------------------------------------------------

==26534==

==26534== Thread #2: Exiting thread still holds 1 lock

==26534==    at 0x4001182: ??? (in /lib/i386-linux-gnu/ld-2.17.so)

==26534==    by 0x405B4D1: __lll_lock_wait (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26534==    by 0x4056ED3: _L_lock_776 (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26534==    by 0x4056D11: pthread_mutex_lock (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26534==    by 0x402E914: pthread_mutex_lock (hg_intercepts.c:510)

==26534==    by 0x80485C6: child_fn (deadlock_helgrind.c:14)

==26534==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==26534==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26534==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26534==

==26534==

==26534== For counts of detected and suppressed errors, rerun with: -v

==26534== Use --history-level=approx or =none to gain increased speed, at

==26534== the cost of reduced accuracy of conflicting-access information

==26534== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0
Lock was previously acquired   对于自身线程来讲  这样的做法明显出问题 它自身还在尝试获取这个lock 这样就导致死锁的发生。可以定位到==26534==    by 0x80485C6: child_fn (deadlock_helgrind.c:14)出问题了 所以这个helgrind解决这类问题时还是非常的厉害的~!
接下来看一个2 mutex导致的问题:

#include <pthread.h>

pthread_mutex_t mut_thread;

pthread_mutex_t mut_thread1;

int var = 0;

void* child_fn ( void* arg ) {

pthread_mutex_lock(&mut_thread);

pthread_mutex_lock(&mut_thread1);

var++;

pthread_mutex_unlock(&mut_thread);

pthread_mutex_unlock(&mut_thread1);

return NULL;

}

void* child_fn1(void *arg)

{

pthread_mutex_lock(&mut_thread1);

pthread_mutex_lock(&mut_thread);

var++;

pthread_mutex_unlock(&mut_thread1);

pthread_mutex_unlock(&mut_thread);

return NULL;

}

int main ( void ) {

pthread_t child;

pthread_t child2;

pthread_mutex_init(&mut_thread,NULL);

pthread_mutex_init(&mut_thread1,NULL);

pthread_create(&child,NULL, child_fn, NULL);

pthread_create(&child2,NULL,child_fn1,NULL);

pthread_join(child,NULL);

pthread_join(child2,NULL);

return 0;

}

加锁顺序导致死锁问题

==26785== Helgrind, a thread error detector

==26785== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.

==26785== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info

==26785== Command: ./deadlock_helgrind

==26785==

==26785== ---Thread-Announcement------------------------------------------

==26785==

==26785== Thread #3 was created

==26785==    at 0x415B3C8: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26785==

==26785== ----------------------------------------------------------------

==26785==

==26785== Thread #3: lock order "0x804A038 before 0x804A050" violated

==26785==

==26785== Observed (incorrect) order is: acquisition of lock at 0x804A050

==26785==    at 0x402E95D: pthread_mutex_lock (hg_intercepts.c:518)

==26785==    by 0x8048637: child_fn1 (deadlock_helgrind.c:22)

==26785==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==26785==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26785==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26785==

==26785==  followed by a later acquisition of lock at 0x804A038

==26785==    at 0x402E95D: pthread_mutex_lock (hg_intercepts.c:518)

==26785==    by 0x8048643: child_fn1 (deadlock_helgrind.c:23)

==26785==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==26785==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26785==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26785==

==26785== Required order was established by acquisition of lock at 0x804A038

==26785==    at 0x402E95D: pthread_mutex_lock (hg_intercepts.c:518)

==26785==    by 0x80485ED: child_fn (deadlock_helgrind.c:13)

==26785==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==26785==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26785==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26785==

==26785==  followed by a later acquisition of lock at 0x804A050

==26785==    at 0x402E95D: pthread_mutex_lock (hg_intercepts.c:518)

==26785==    by 0x80485F9: child_fn (deadlock_helgrind.c:14)

==26785==    by 0x402E5F6: mythread_wrapper (hg_intercepts.c:233)

==26785==    by 0x4054D77: start_thread (in /lib/i386-linux-gnu/libpthread-2.17.so)

==26785==    by 0x415B3DD: clone (in /lib/i386-linux-gnu/libc-2.17.so)

==26785==

==26785==

==26785== For counts of detected and suppressed errors, rerun with: -v

==26785== Use --history-level=approx or =none to gain increased speed, at

==26785== the cost of reduced accuracy of conflicting-access information

==26785== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 9 from 9

这是观察法得出的  加锁顺序出错导致了这种情况的发生。 
posix_thread erro这里就不列举了  这个完全是看基础。

下篇待续

Valgrind的多线程调试工具的更多相关文章

  1. Valgrind,内存调试工具

    Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具 官网:http://valgrind.org/ 用户开发手册地址:http://valgrind.org/docs/manu ...

  2. http调试工具,linux调试工具

    charles Linux下Web性能压力测试工具http_load linux 下的socket 调试工具 netcat Linux下四款Web服务器压力测试工具(http_load.webbenc ...

  3. 内存排查 valgrind

    内存问题排查工具 --- valgrind 1. 概述 2. Valgrind 3. 内存泄漏监测 3.1. 示例代码 3.2. 编译它 3.3. 用Valgrind监测进程的内存泄漏 4. 悬挂指针 ...

  4. 内存问题排查工具 --- valgrind

    1. 概述 2. Valgrind 3. 内存泄漏监测 3.1. 示例代码 3.2. 编译它 3.3. 用Valgrind监测进程的内存泄漏 4. 悬挂指针 4.1. 示例代码 4.2. Valgri ...

  5. FireFox VS Chrome 之 调试篇

    一个完美的调试工具,FireBug! 精确跟踪每一步.仅仅要按下图所看到的,选择"脚本",然后在下方选择脚本所在的文件就可以对该文本的运行进行断点跟踪. 而且仅当一个线程运行结束后 ...

  6. C++内存泄漏检测工具

    C++内存泄漏检测工具 1.VC自带的CRT:_CrtCheckMemory   调试器和 CRT 调试堆函数 1.1用法: /************************************ ...

  7. golang goroutine 介绍

    Goroutine 是用户态自己实现的线程,调度方式遇到IO/阻塞点方式就会让出cpu时间(其实也看编译器的实现,如果TA在代码里面插入一些yield,也是可以的. 反正现在不是抢占式的.) 不能设置 ...

  8. iOS 10 的一个重要更新-线程竞态检测工具 Thread Sanitizer

    本文介绍了 Xcode 8 的新出的多线程调试工具 Thread Sanitizer,可以在 app 运行时发现线程竞态. 想想一下,你的 app 已经近乎大功告成:它经过精良的打磨,单元测试全覆盖. ...

  9. valgrind 打印程序调用树+进行多线程性能分析

    使用valgrind的callgrind工具进行多线程性能分析 yum install valgrind / wget http://valgrind.org/downloads/valgrind-3 ...

随机推荐

  1. HDU 5842 Lweb and String(Lweb与字符串)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  2. Linq排序,获取前5条数据

    _dic = _dic.OrderByDescending(x => x.Value).ToDictionary(x=>x.Key,x=>x.Value); var Num = _d ...

  3. Lucas定理

    Lucas' theorem In number theory, Lucas's theorem expresses the remainder of division of the binomial ...

  4. python decorator的理解

    一.decorator的作用 装饰器本质上是一个Python函数,可以让其他函数在不做任何代码变动的前提下增加额外功能. 装饰器的返回值也是一个函数对象.python里函数也是对象. 它经常用于有切面 ...

  5. MUMmer 3使用方法

    DNA和核苷酸的快速比对软件包,基于suffix tree 数据结构,快速.图形化.模块可用于其他软件.可进行大基因组比对.多对多基因组比对. The MUMmer Home Page The MUM ...

  6. iframe 根据加载内容调整高度

    iframe标签代码 <iframe id="checkListFrame" name="checkListFrame"    src="Ind ...

  7. 20169212《Linux内核原理与分析》第三周作业

    最近,深入的阅读了<Linux内核设计与实现>这本书,以下是碰到的一些问题,在此和大家进行交流学习. 碰到的问题 1.为什么不要在linux内核中使用浮点数(这个问题由于书上讲的不够明白, ...

  8. Objective-C( protocol协议)

    protocol 协议 protocol:用来声明方法 1.协议的定义 @protocol 协议名称 <NSObject> // 方法声明列表.... @end 2.如何遵守协议 1> ...

  9. eclipse改变theme

    https://github.com/eclipse-color-theme/eclipse-color-theme.git https://github.com/eclipse-color-them ...

  10. jquery 获取下拉框值与select text

    下面先介绍了很多jquery获取select属性的方法,同时后面的实例我们讲的是jquery 获取下拉框值与select text代码. 下面先介绍了很多jquery获取select属性的方法,同时后 ...