C pthread_join似乎在修改我的循环索引
我的代码(见下文)产生了一种奇怪的行为。输出为:C pthread_join似乎在修改我的循环索引,c,multithreading,for-loop,pthreads,pthread-join,C,Multithreading,For Loop,Pthreads,Pthread Join,我的代码(见下文)产生了一种奇怪的行为。输出为: Testing whether there are problems with concurrency ...rc is 0. i is 0 .rc is 0. i is 0 .rc is 3. i is 1 .rc is 0. i is 0 .rc is 3. i is 1 .rc is 3. i is 2 .rc is 0. i is 0 .rc is 3. i is 1 .rc is 3. i is 2 .rc is 3. i is 3 .
Testing whether there are problems with concurrency ...rc is 0. i is 0
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 3. i is 4
.rc is 0. i is 0
Segmentation fault (core dumped)
我试图调试它,但只发现在pthread_join之后我被重置为0。这使我得出这样的结论,修改必须发生在那里的某个地方。但我什么也找不到。我觉得有点傻,因为这不是一段很难的代码。我没有注意到什么
操作系统是Ubuntu 14.04。N_线程当前设置为10,N_运行数为10000
主线程:
pthread_t threads[N_THREADS];
pthread_attr_t attr;
int i;
int rc;
int status;
printf("Testing whether there are problems with concurrency ...");
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < N_THREADS; i++){
if (i) {
rc = pthread_create(&(threads[i]), &attr, addRemove, 0);
} else {
rc = pthread_create(&(threads[i]), &attr, readStuff, 0);
}
if (rc) return rc;
}
for(i = 0; i < N_THREADS; i++) {
rc = pthread_join(threads[i], (void*) &status);
// if(rc == 3)
printf("rc is %d. i is %d\n", rc, i);
// if (rc) return rc;
if (status) return status;
printf(".");
}
pthread_attr_destroy(&attr);
return 0;
pthread_t threads[N_threads];
pthread_attr_t attr;
int i;
int rc;
智力状态;
printf(“测试是否存在并发问题…”);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,pthread_CREATE_JOINABLE);
对于(i=0;i
工作线程:
void* readStuff(void* a)
{
int i;
for (i = 0; i< N_RUNS; i++){
;
}
pthread_exit((void*)0);
}
void* addRemove(void* a)
{
int i;
for (i = 0; i< N_RUNS; i++){
;
}
pthread_exit((void*)0);
}
void*readStuff(void*a)
{
int i;
对于(i=0;i
除了主线程和上面代码中创建的线程之外,没有其他线程
我认为您的问题在于
pthread\u join
。从手册页:
int pthread_join(pthread_t thread, void **retval);
...
If retval is not NULL, then pthread_join() copies the exit status of the tar‐
get thread (i.e., the value that the target thread supplied to
pthread_exit(3)) into the location pointed to by *retval. If the target
thread was canceled, then PTHREAD_CANCELED is placed in *retval.
int pthread_join(pthread_t thread,void**retval);
...
如果retval不为NULL,则pthread_join()复制tar的退出状态
获取线程(即,目标线程提供给的值
pthread_exit(3))进入*retval指向的位置。如果目标
线程被取消,然后PTHREAD_cancelled被放置在*retval中。
请注意,它采用了一个void**
,这意味着它将用void*
(大小为8,64位)覆盖retval
指向的内容。您正在传递一个int*
(即&status
),它是指向大多数平台上大小为4的对象的指针
因此,pthread\u join
将覆盖内存。相反,根据函数原型将status
声明为void*
您也在测试状态
;我不知道你在这里想要实现什么
通常,使用
-Wall
编译会显示这些错误。连接部分中有两个for循环。这是打字错误吗?提供一个完整的、可编译的示例如何?我在问题上加了一个。在使用石膏时要更加小心pthread_exit((void*)0)
是不必要的,pthread_exit(NULL)
或pthread_exit(0)
都可以。pthread\u join
调用是错误的,但是被您的强制转换隐藏了。声明一个void*
变量并将其地址传递给pthread\u join
(不带强制转换)以恢复状态。-Wall-Wextra没有通知我这一点。但它解决了问题!谢谢如果我说这不会发生在32位系统上,对吗?是的(我错过了演员阵容)。是的,sizeof(void*)==sizeof(int)
在32位上。它不会将8个字节写入32位上的4字节内存位置,但您的代码仍然是错误的,因为pthread\u join
会将地址写入status