我有以下代码,编译和执行没有错误,但编译器显示了一些我想“解决”的警告。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
typedef struct s_Barrier{
sem_t sEntry, sMutEx, sExit;
int nTaskInBarrier;
}Barrier;
void createTasks(pthread_t threads[]);
void task(void *arg);
void initBarrier(Barrier *pb, int n);
void destroyBarrier(Barrier *pb);
void waitInBarrier(Barrier *pb);
Barrier barrier;
int nTask = 5;
int main(void) {
pthread_t threads[nTask];
initBarrier(&barrier,nTask);
createTasks(threads);
destroyBarrier(&barrier);
return 0;
}
void createTasks(pthread_t threads[]){
int i;
for(i = 0; i < nTask; i++){
pthread_create(&threads[i], NULL, task, (void*)i);
}
for(i = 0; i < nTask; i++){
pthread_join(threads[i], NULL);
}
}
void initBarrier(Barrier *pb, int n){
pb->nTaskInBarrier = 0;
sem_init(&pb->sEntry,0,n);
sem_init(&pb->sExit,0,1);
sem_init(&pb->sMutEx,0,1);
}
void destroyBarrier(Barrier *pb){
sem_destroy(&pb->sEntry);
sem_destroy(&pb->sExit);
sem_destroy(&pb->sMutEx);
}
void task(void *arg){
int i = (int) arg;
while(1){
printf("I'm thread %d\n",i);
waitInBarrier(&barrier);
}
}
void waitInBarrier(Barrier *pb){
int x;
int i;
sem_wait(&pb->sEntry);
sem_wait(&pb->sMutEx);
x = ++pb->nTaskInBarrier;
sem_post(&pb->sMutEx);
if(x < nTask){
sem_wait(&pb->sExit);
}else{
for(i = 0; x < nTask ; i++){
sem_post(&pb->sExit);
}
}
sem_wait(&pb->sMutEx);
x = --pb->nTaskInBarrier;
sem_post(&pb->sMutEx);
if(x == 0){
for(i = 0; x < nTask ; i++){
sem_post(&pb->sEntry);
}
}
}
当我使用“gcc -o Barrier 3.4Barrier.c -pthread”进行编译时,请获取以下警告。
3.4Barrier.c: In function ‘createTasks’:
3.4Barrier.c:47:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&threads[i], NULL, task, (void*)i);
^
3.4Barrier.c:47:37: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [-Wincompatible-pointer-types]
pthread_create(&threads[i], NULL, task, (void*)i);
^
In file included from 3.4Barrier.c:13:0:
/usr/include/pthread.h:233:12: note: expected ‘void * (*)(void *)’ but argument is of type ‘void (*)(void *)’
extern int pthread_create (pthread_t *__restrict __newthread,
^
3.4Barrier.c: In function ‘task’:
3.4Barrier.c:70:10: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
int i = (int) arg;
答案 0 :(得分:3)
第一个问题是task
应该返回void*
而不是void
,正如pthread_create
原型所指定的那样:
void* task(void *arg) {
// ...
return NULL;
}
这很容易解决。
第二个问题是你不应该以这种方式传递i
- 你不应该将int
投射到void*
。将i
传递给task
的一种方法是分配一小块内存并使用它 1 :
for(i = 0; i < nTask; i++){
int *pi = malloc(sizeof(int));
if (pi == NULL) {
// Something wrong...
}
*pi = i;
pthread_create(&threads[i], NULL, task, pi);
}
和
void* task(void *arg){
int i = *(int*)arg; // Cast to `int*` and then dereference.
free(arg); // Don't forget this!
while(1){
printf("I'm thread %d\n",i);
waitInBarrier(&barrier);
}
return NULL;
}
1 请勿尝试将(void*)&i
直接传递给pthread_create
,因为无法保证*(int*)arg
会在增加之前进行评估for
循环,这样您可能会在读取其值之前发现i
更改的奇怪行为。
答案 1 :(得分:0)
更改此
void createTasks(pthread_t threads[]){
int i;
for(i = 0; i < nTask; i++){
pthread_create(&threads[i], NULL, task, (void*)i);
}
为:
void createTasks(pthread_t threads[]){
int i;
for(i = 0; i < nTask; i++){
int *arg = malloc(Sizeof(int));
*arg = i;
pthread_create(&threads[i], NULL, task, (void*)arg);
}
然后改变:
void task(void *arg){
int i = (int) arg;
while(1){
printf("I'm thread %d\n",i);
waitInBarrier(&barrier);
}
}
到
void *task(void *arg){
int i = *((int *) arg);
free(arg);
while(1){
printf("I'm thread %d\n",i);
waitInBarrier(&barrier);
}
return 0;
}
这样可以避免在遇到无效问题时遇到的错误,并且内注的大小不同。
它还将为任务
提供写入返回类型答案 2 :(得分:0)
进行一些更改:
第13行和第59行中的1- void *task(void *arg);
因为task用作pthread_create
函数
第60行中的int pthread_create(pthread_t * thread,const pthread_attr_t * attr, void *( start_routine)(void ),void * arg);
2- int i = *((int *)arg);
3-编译像这样的gcc Barrier.c -lpthread