Подтвердить что ты не робот

Pthread_create: передача целого числа в качестве последнего аргумента

У меня есть следующие функции:

void *foo(void *i) {
    int a = (int) i;
}

int main() {
    pthread_t thread;
    int i;
    pthread_create(&thread, 0, foo, (void *) i);
}

При компиляции есть некоторые ошибки в кастинге ((void *) i и int a = (int) i). Как я могу передать целое число как последний аргумент pthread_create правильно?

4b9b3361

Ответ 1

Основываясь на ответе szx (дайте ему кредит), вот как это будет работать в вашем цикле for:

void *foo(void *i) {
    int a = *((int *) i);
    free(i);
}

int main() {
    pthread_t thread;
    for ( int i = 0; i < 10; ++1 ) {
        int *arg = malloc(sizeof(*arg));
        if ( arg == NULL ) {
            fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
            exit(EXIT_FAILURE);
        }

        *arg = i;
        pthread_create(&thread, 0, foo, arg);
    }

    /*  Wait for threads, etc  */

    return 0;
}

На каждой итерации цикла вы выделяете новую память, каждый с другим адресом, поэтому вещь, которая передается в pthread_create() на каждой итерации, различна, поэтому ни один из ваших потоков не пытается получить доступ к и вы не получите никаких проблем с безопасностью потока, как если бы вы просто передали адрес i. В этом случае вы также можете настроить массив и передать адреса элементов.

Ответ 2

Вы можете выделить int в куче и передать ее на pthread_create(). Затем вы можете освободить его в своей функции потока:

void *foo(void *i) {
    int a = *((int *) i);
    free(i);
}

int main() {
    pthread_t thread;
    int *i = malloc(sizeof(*i));
    pthread_create(&thread, 0, foo, (void *) i);
}

Ответ 3

Вы должны указать адрес i (а не значение i, как сейчас) в последнем аргументе pthread_create().

pthread_create(&thread, 0, foo, (void *) &i);
                                         ^  is missing

И кастинг ошибочен и в вашей функции. Это должно быть:

int a = *((int*) i);
  • Если вы намерены прочитать значение, вы также должны инициализировать i до некоторого значения в main(), поскольку оно теперь не инициализировано.

2 Используйте правильное определение для main():

 int main(void) 

или int main(int argc, char *argv[]) или его эквивалент.

Ответ 4

Старый вопрос, но сегодня я столкнулся с такой же проблемой, и решил не идти по этому пути. Мое приложение действительно касалось производительности, поэтому я решил, что этот массив int объявлен статически.

Поскольку я не знаю много приложений, где ваш pthread_join/pthread_cancel находится в другой области, чем ваш pthread_create, я выбрал этот способ:

#define NB_THREADS 4

void *job(void *_i) {
  unsigned int i = *((unsigned int *) _i);
}

int main () {
  unsigned int ints[NB_THREADS];
  pthread_t    threads[NB_THREADS];
  for (unsigned int i = 0; i < NB_THREADS; ++i) {
    ints[i] = i;
    pthread_create(&threads[i], NULL, job, &ints[i]);
  }
}

Я нахожу его более элегантным, более эффективным, и вам не нужно беспокоиться о освобождении, поскольку он живет только в этой области.

Ответ 5

Хотя это старый вопрос, есть один недостающий вариант, когда вам нужно только передать положительное целое число, например дескриптор: вы можете передать его напрямую в качестве адреса, в то время как он взломает его, он хорошо работает и не выделяет ничего: )

ПРИМЕЧАНИЕ. Размер целого должен соответствовать размеру указателя на вашей ОС, но в настоящее время большинство систем являются собственными 64 битами.

#include <pthread.h>
#include <inttypes.h>
#include <stdio.h>

void *_thread_loop(void *p)
{
  uint64_t n = (uint64_t)p;

  printf("received %llu\n", n);

  return NULL;
}



int main(int argc, char const *argv[])
{
  pthread_t read_thread_id;
  uint64_t n = 42;
  pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);

  pthread_join(read_thread_id, NULL);
  return 0;
}