Helgrind在valgrind抱怨简单的互斥
helgrind in valgrind complains with simple mutex
我正在调试一些线程代码,并且正在使用valgrind——tool=helgrind,由于某些原因helgrind不喜欢下面的简单示例。
在启动一个线程之前,我锁定了互斥锁。在线程结束时,我正在解锁,从而确保一次只有一个线程可以运行,假设互斥锁将被锁定,直到线程完成。
为什么根据valgrind这是无效的?
这是一个更大的程序的一部分,其中我的主程序正在读取/解析数据,它将启动一个分析线程,但我只希望一次运行一个分析线程。
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex;
void *inner(void *ptr){
size_t threadid=(size_t)ptr;
int sleepval = lrand48() % 5 +1;
fprintf(stderr,"thread: %lu will wait:%dn",threadid,sleepval);fflush(stderr);
sleep(sleepval);
pthread_mutex_unlock(&mutex);
}
int outer(size_t ntimes){
pthread_t thread1;
size_t i;
for(i=0;i<ntimes;i++){
pthread_mutex_lock(&mutex);
if(pthread_create( &thread1, NULL, inner, (void*) i))
fprintf(stderr,"Problems creating threadn");
}
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
int main(){
pthread_mutex_init(&mutex, NULL);
outer(3);
return 0;
}
==8326== Helgrind, a thread error detector
==8326== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.
==8326== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==8326== Command: ./a.out
==8326==
thread: 0 will wait:1
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #1 is the program's root thread
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Attempt to re-lock a non-recursive lock I already hold
==8326== at 0x4C32010: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326== Lock was previously acquired
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #2 was created
==8326== at 0x515543E: clone (clone.S:74)
==8326== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
==8326== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
==8326== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400976: outer (threadTest.c:22)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #2 unlocked lock at 0x6010A0 currently held by thread #1
==8326== at 0x4C325C0: pthread_mutex_unlock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400937: inner (threadTest.c:11)
==8326== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4E45181: start_thread (pthread_create.c:312)
==8326== by 0x515547C: clone (clone.S:111)
==8326== Lock at 0x6010A0 was first observed
==8326== at 0x4C31DDA: pthread_mutex_init (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009D0: main (threadTest.c:31)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Bug in libpthread: recursive write lock granted on mutex/wrlock which does not support recursion
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
thread: 1 will wait:4
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #3 was created
==8326== at 0x515543E: clone (clone.S:74)
==8326== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
==8326== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
==8326== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400976: outer (threadTest.c:22)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #3 unlocked lock at 0x6010A0 currently held by thread #1
==8326== at 0x4C325C0: pthread_mutex_unlock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400937: inner (threadTest.c:11)
==8326== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4E45181: start_thread (pthread_create.c:312)
==8326== by 0x515547C: clone (clone.S:111)
==8326== Lock at 0x6010A0 was first observed
==8326== at 0x4C31DDA: pthread_mutex_init (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009D0: main (threadTest.c:31)
==8326==
thread: 2 will wait:1
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Attempt to re-lock a non-recursive lock I already hold
==8326== at 0x4C32010: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009B1: outer (threadTest.c:25)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326== Lock was previously acquired
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #4 was created
==8326== at 0x515543E: clone (clone.S:74)
==8326== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
==8326== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
==8326== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400976: outer (threadTest.c:22)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #4 unlocked lock at 0x6010A0 currently held by thread #1
==8326== at 0x4C325C0: pthread_mutex_unlock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400937: inner (threadTest.c:11)
==8326== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4E45181: start_thread (pthread_create.c:312)
==8326== by 0x515547C: clone (clone.S:111)
==8326== Lock at 0x6010A0 was first observed
==8326== at 0x4C31DDA: pthread_mutex_init (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009D0: main (threadTest.c:31)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Bug in libpthread: recursive write lock granted on mutex/wrlock which does not support recursion
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009B1: outer (threadTest.c:25)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326==
==8326== For counts of detected and suppressed errors, rerun with: -v
==8326== Use --history-level=approx or =none to gain increased speed, at
==8326== the cost of reduced accuracy of conflicting-access information
==8326== ERROR SUMMARY: 9 errors from 7 contexts (suppressed: 104 from 61)
直接的问题是您在一个线程中锁定了一个互斥锁,而在另一个线程中解锁了它。您还可以尝试在同一个线程中两次锁定同一个非递归互斥锁。因为只有获得锁的线程才能释放它,这将是一个死锁。
要实现你可能想要的语义,你可以直接连接新创建的线程:连接将阻塞,直到相应的线程退出。
或者,您可以保护一个活动线程数,该线程数在创建线程时递增,在线程结束时递减。结束线程也会发出一个条件变量的信号。创建线程将检查计数,如果计数过高,则等待条件变量。
让一个处理器线程使用并可能阻塞一个作业队列,这可能是限制工作线程数量的最简单和最有效的方法。
从pthread_mutex_lock
的手册页:
如果一个线程试图解锁一个它还没有锁定的互斥锁如果互斥锁被解锁,将导致未定义的行为。
所以你必须在同一个线程中锁定和解锁互斥锁。
你的函数也应该返回一个与原型匹配的值。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
pthread_mutex_t mutex;
void *inner(void *ptr){
size_t threadid = *(size_t *)ptr;
int sleepval = rand() % 5 +1;
pthread_mutex_lock(&mutex);
fprintf(stderr,"thread: %lu will wait:%dn",threadid,sleepval);
fflush(stderr);
sleep(sleepval);
pthread_mutex_unlock(&mutex);
return NULL;
}
int outer(size_t ntimes){
pthread_t thread[ntimes];
size_t i, id[ntimes];
for(i=0;i<ntimes;i++){
id[i] = i;
if(pthread_create(thread + i, NULL, inner, &id[i]))
fprintf(stderr,"Problems creating threadn");
}
for(i=0;i<ntimes;i++)
pthread_join(thread[i], NULL);
return 0;
}
int main(void){
pthread_mutex_init(&mutex, NULL);
outer(3);
return 0;
}
这对我有用。我还添加了缺失的头,并更改了函数参数以匹配新的要求。
旁注:outer
函数现在使用可变长度数组,因此它只在C99中工作,而不是在c++中(该问题标记为两者)。
相关文章:
- valgrind-hellgrind与泄漏检查的结果不同
- 在c++中用vector填充一个简单的动态数组
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的简单if-else语句是如何无法访问的代码
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 一种在C++中读取TXT配置文件的简单方法
- 关于简单C++函数(is_palindrome)的逻辑的问题
- 显示错误输出的简单数组排序程序
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 退出简单while循环时出现问题
- 为什么简单的算术减法在"if"条件下不起作用?
- 额外分配valgrind
- C++-字符串是否包含一个带有简单循环的单词
- 关于 c++ 函数中指针赋值的简单问题
- Valgrind 检查简单多线程 C++11 得到 SIG11 错误
- Valgrind在简单迭代器类中检测到无效读取错误
- 为什么一个简单的SDL程序会报告Valgrind中的内存泄漏?
- Helgrind在valgrind抱怨简单的互斥
- valgrind报告BSONObj::toString中未初始化的值,使用GENOID创建一个简单的BSON对象