J'ai les fonctions suivantes:
void *foo(void *i) {
int a = (int) i;
}
int main() {
pthread_t thread;
int i;
pthread_create(&thread, 0, foo, (void *) i);
}
Lors de la compilation, il y a quelques erreurs lors de la conversion ((void *) i
Et int a = (int) i
). Comment passer correctement un entier comme dernier argument de pthread_create
?
En s'appuyant sur la réponse de szx (alors donnez-lui le crédit), voici comment cela fonctionnerait dans votre boucle 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;
}
À chaque itération de la boucle, vous allouez de la nouvelle mémoire, chacune avec une adresse différente, donc la chose qui est passée à pthread_create()
à chaque itération est différente, donc aucun de vos threads ne finit par essayer d'accéder la même mémoire et vous n'obtenez aucun problème de sécurité des threads comme vous le feriez si vous veniez de passer l'adresse de i
. Dans ce cas, vous pouvez également configurer un tableau et transmettre les adresses des éléments.
Vous pouvez allouer un int
sur le tas et le passer à pthread_create()
. Vous pouvez ensuite le désallouer dans votre fonction de thread:
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);
}
Vous devez convertir l'adresse de i
(plutôt que la valeur de i
comme vous le faites maintenant) dans le dernier argument de pthread_create ().
pthread_create(&thread, 0, foo, (void *) &i);
^ is missing
Et le casting est mauvais dans votre fonction aussi. CA devrait etre:
int a = *((int*) i);
i
à une valeur dans main () car elle n'est pas initialisée maintenant.2 Utilisez la bonne définition pour main ():
int main(void)
ou int main(int argc, char *argv[])
ou son équivalent.
Vieille question, mais j'ai fait face au même problème aujourd'hui, et j'ai décidé de ne pas suivre cette voie. Mon application concernait vraiment les performances, j'ai donc choisi de déclarer statiquement ce tableau de int
s.
Comme je ne connais pas beaucoup d'applications où votre pthread_join
/pthread_cancel
est dans une autre portée que votre pthread_create
, J'ai choisi cette voie:
#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]);
}
}
Je le trouve plus élégant, plus efficace, et vous n'avez pas à vous soucier de la libération car elle ne vit que dans cette étendue.
Bien qu'il s'agisse d'une vieille question, il manque une option lorsque tout ce dont vous avez besoin est de passer un entier positif comme un descripteur: vous pouvez le passer directement en tant qu'adresse, tandis que c'est un hack, cela fonctionne bien et évitez d'allouer quoi que ce soit :)
REMARQUE: la taille de l'entier doit correspondre à la taille d'un pointeur sur votre système d'exploitation mais de nos jours la plupart des systèmes sont en 64 bits natifs.
#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;
}