我下面的代码来自一本书,该书是在Ubuntu 18.4上使用Eclipse -O0 -g3编译的
#include <pthread.h>
#include <stdio.h>
void *myThread( void *arg )
{
printf( "Thread %d started\n", (int)arg );
pthread_exit( arg );
}
#define MAX_THREADS 5
int main()
{
volatile int i;
int status;
int ret;
pthread_t threadIds[MAX_THREADS];
for (i = 0 ; i < MAX_THREADS ; i++) {
ret = pthread_create( &threadIds[i], NULL, myThread, (void *)i );
if (ret != 0) {
printf( "Error creating thread %d\n", (int)threadIds[i] );
}
}
for (i = 0 ; i < MAX_THREADS ; i++) {
printf("----------- i = %d\n",i);
ret = pthread_join( threadIds[i], (void **)&status );
if (ret != 0) {
printf( "Error joining thread %d\n", (int)threadIds[i] );
} else {
printf( "Status = %d\n", status );
}
}
return 0;
}
此代码可以正常工作并产生输出
----------- i = 0
Thread 3 started
Thread 0 started
Status = 0
----------- i = 1
Thread 2 started
Thread 1 started
Status = 1
----------- i = 2
Status = 2
----------- i = 3
Status = 3
----------- i = 4
Thread 4 started
Status = 4
但是,如果忽略变量i声明中的 volatile 关键字,则会产生以下输出:
Thread 1 started
Thread 0 started
Thread 2 started
Thread 3 started
----------- i = 0
Status = 0
----------- i = 1
Status = 1
----------- i = 1
Error joining thread -947054848
----------- i = 2
Status = 2
----------- i = 1
Error joining thread -947054848
----------- i = 2
Error joining thread -955447552
----------- i = 3
Status = 3
----------- i = 1
Error joining thread -947054848
----------- i = 2
Error joining thread -955447552
----------- i = 3
Error joining thread -963840256
----------- i = 4
Thread 4 started
Status = 4
----------- i = 1
Error joining thread -947054848
----------- i = 2
Error joining thread -955447552
----------- i = 3
Error joining thread -963840256
----------- i = 4
Error joining thread -1073744128
请帮助我确定可能导致此问题的问题。
答案 0 :(得分:4)
在您的代码中:
int status;
// ...
pthread_join( threadIds[i], (void **)&status );
这是严格的别名冲突。 pthread_join
向位置写入类型void *
的值,但是您提供了int
的位置。这会导致不确定的行为,意味着任何事情都可能发生。
您的系统上可能发生的情况是写越界(int
= 4字节,void *
= 8字节),使堆栈混乱,导致混乱。
您可以使用以下方法解决此问题:
void *status;
// ...
pthread_join( threadIds[i], &status );
以后,如果要使用%d
打印状态,请使用(int)status
作为参数。