使用Valgrind和ThreadSanitizer检测多线程错误

做毕设的时候,我曾经遇到一个多线程的BUG。这个BUG表现得较为诡异,会导致数据随机出错。由于找不出什么规律,一开始我还是挺头疼的。查了半天后我发现,相关的日志有多线程下共享数据访问问题的迹象(即所谓的data race),所以很快确诊是多线程部分代码存在逻辑错误。这个问题的解决办法很简单,就是把相关的代码review下,找出data race的部分并加以修正。虽然BUG是搞定了,不过我还是想找到一个自动化工具,能够检测出代码中潜在的线程安全问题。这样就能把BUG消灭在萌芽之中,而不是等到事后才睁大眼睛揪它出来。

搜索了下,发现了两个适合做这个的工具,Valgrind和ThreadSanitizer。今天就来介绍下这两个工具。

Valgrind

Valgrind一般用做内存泄露和访存越界检测,除此之外,其实它也支持对data race及一些简单的多线程问题的检查。Valgrind工具集里面,helgrind和drd都能用来完成这种检测。你可以用valgrind --tool=helgrindvalgrind --tool=drd来启用它。只要应用使用的线程模型是POSIX thread(pthread),这两个工具就能进行检测。这两个工具间差别不大,下面我就基于helgrind来介绍下用法:

先上一段有问题的示例代码:

// raceCondition.cpp
#include <pthread.h>

void *write_buffer(void *args)
{
    pthread_t *buffer = static_cast<pthread_t *>(args);
    *buffer = pthread_self();
    pthread_exit(0);
    return NULL;
}

int main()
{
    pthread_t *buffer = new pthread_t[2];
    pthread_t a, b;

    pthread_create(&a, NULL, write_buffer, buffer);
    pthread_create(&b, NULL, write_buffer, buffer);
    pthread_join(a, NULL);
    pthread_join(b, NULL);
    delete []buffer;

    return 0;
}

这段代码有一个刻意为之的问题,线程a和线程b写入了同一个缓冲区。

用Valgrind可以检测出问题:

==5697== ---Thread-Announcement------------------------------------------
==5697==
==5697== Thread #3 was created
==5697==    at 0x545943E: clone (clone.S:74)
==5697==    by 0x5148199: do_clone.constprop.3 (createthread.c:75)
==5697==    by 0x51498BA: create_thread (createthread.c:245)
==5697==    by 0x51498BA: pthread_create@@GLIBC_2.2.5 (pthread_create.c:611)
==5697==    by 0x4C30E0D: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5697==    by 0x400928: main (in /home/lzx/C/thread_error/a.out)
==5697==
==5697== ---Thread-Announcemen
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值