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
правильно?
Ответы
Ответ 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;
}