投射和争论警告

时间:2016-10-03 07:42:27

标签: c++ c unix pthreads

我有以下代码,编译和执行没有错误,但编译器显示了一些我想“解决”的警告。

这是我的代码:

#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;

3 个答案:

答案 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函数

中函数的指针
  

int pthread_create(pthread_t * thread,const pthread_attr_t * attr,       void *( start_routine)(void ),void * arg);

第60行中的

2- int i = *((int *)arg); 3-编译像这样的gcc Barrier.c -lpthread