2009-05-14 4 views
17

J'ai essayé le passage d'une structure que le 4ème argument de tout en utilisant pthread_create() avec quelque chose comme ceci:Passant structures comme arguments tout en utilisant pthread_create()

pthread_create(&tid1, NULL, calca, &t); //t is the struct 

Maintenant, chaque fois que je tente d'accéder à des variables dans la structure - ta, tb ou tc, je reçois toujours une erreur - demande de membre dans quelque chose qui n'est pas une structure ou un syndicat.

Quelle méthode alternative pourrais-je utiliser pour passer des structures dans le thread?

Répondre

24

Vous créez probablement la structure dans la même portée que pthread_create. Cette structure ne sera plus valide une fois que la portée sera terminée. Essayez de créer un pointeur sur la structure sur le tas et passez ce pointeur de structure à votre thread. N'oubliez pas de supprimer cette mémoire quelque part (dans le thread si vous ne l'utiliserez plus jamais - ou lorsque vous n'en avez plus besoin). En outre, comme cyberconte mentionné, si vous allez accéder à ces données à partir de différents threads, vous devrez verrouiller l'accès à celui-ci avec un mutex ou une section critique.

Édition 14 mai 2009 @ 12:19 PM EST: Aussi, comme d'autres personnes l'ont mentionné, vous devez convertir votre paramètre au type correct.

Si vous passez une variable qui est une structure globale (que vous semblez insister sur), la fonction thread devra jeter le type:

void my_thread_func(void* arg){ 
    my_struct foo = *((my_struct*)(arg)); /* Cast the void* to our struct type */ 
    /* Access foo.a, foo.b, foo.c, etc. here */ 
} 

Ou, si vous passez un pointeur vers votre structure:

+0

En fait, j'ai créé le thread dans la fonction principale et créé la structure juste après avoir inclus les fichiers d'en-tête. Donc, il devrait être accessible par toutes les fonctions (corrigez-moi si je me trompe). – skinderneath

+0

Votre modification récente a été le message le plus utile ici jusqu'à maintenant. Merci. – skinderneath

+1

Merci, ceci a sauvé mon bacon. – g33kz0r

0

Vous pouvez utiliser la mémoire partagée ou une variable globale (si rien d'autre n'a besoin de cet argument) ou une liste liée si ce sont des threads qui alimentent des données. N'oubliez pas de verrouiller vos variables en cours de partage de threads.

Sans le code réel offensant, je ne peux pas vous dire ce que vous faites mal dans votre implémentation actuelle.

+0

Suppression du vote en raison de l'expansion de la réponse. –

2

Si vous êtes dans votre fonction de thread, l'argument que vous passez est un void *. Vous devrez le convertir en structure avant de pouvoir l'utiliser comme tel.

void my_thread_func(void* arg){ 
    my_struct foo = (my_struct)(*arg); /* Cast the void* to our struct type */ 
    /* Access foo.a, foo.b, foo.c, etc. here */ 
} 
+0

Je l'ai fait mais maintenant je reçois une erreur "dereferencing 'void *' pointer". – skinderneath

+0

Harper voulait écrire: my_struct foo = * (my_struct *) arg; ou my_struct * foo = (my_struct *) arg; –

+0

Utilisé cette idée et le montage de Lyndsey Ferguson posté - 14 mai 2009 @ 12:19 PM EST. – skinderneath

0

Ce message d'erreur signifie que vous ne déréférencer pas le pointeur.

Vous dites « ta » au lieu de « T-> un »

 
[[email protected] ~]$ cat testitx.c 
struct x { 
     int a, b; 
}; 

int main(int argc, char *argv[]) 
{ 
     struct x y, *z; 

     z = &y; 
     z.a = 10; 
} 
[[email protected] ~]$ cc -c testitx.c 
testitx.c: In function `main': 
testitx.c:10: error: request for member `a' in something not a structure or union 
[[email protected] ~]$ 
+0

Ne aide pas. J'ai utilisé la solution de Harper Shelby pour obtenir une erreur "dereferencing 'void *' pointer". – skinderneath

0

Je souvent l'habitude de faire les mêmes erreurs figurant dans les autres réponses, mais maintenant je prends une approche légèrement différente qui se déplace le potentiel d'erreur de la fonction de threading à l'appel pthread_create.

Je déclare et définit la fonction de filetage d'une manière « normale »:

void *ThreadFunction(sPARAMETERS *Params) { 

    // do my threading stuff... 

} 

et quand je pthread_create, je dois utiliser un casting:

pthread_create(&ThreadId,0,(void*(*)(void*)) &ThreadFunction,&Params); 

Je presque jamais oublié de utilisez le & sur le Params, et le compilateur se chargera de toutes les erreurs que je fais à l'autre bout. Fonctionne très bien pour les rappels, aussi.

+0

Techniquement parlant, il s'agit d'un comportement non défini - bien que sur la plupart des compilateurs, il fonctionnera pour les pointeurs de structure ordinaires. Ne l'essayez pas avec des pointeurs de fonction membres C++ ... – bdonlan

+0

Je ne comprends pas comment cela aide à résoudre mon problème. Ces moulages que vous avez utilisés sont beaucoup trop cryptiques. – skinderneath

1
  1. Créer un sémaphores

  2. Créer une autre structure qui se compose d'un pointeur sur votre structure et la poignée de sémaphores

  3. Passer un pointeur vers cette nouvelle structure à pthread_create

  4. En le thread parent, c'est-à-dire celui appelé pthread_create, attend sur le sémaphore

  5. Dans le fil de l'enfant, copiez les membres de votre structure à des variables locales ou les enregistrer ailleurs

  6. Dans le fil de l'enfant, signaler la sémaphores

  7. Dans le thread parent, fermer le sémaphores

0

my_struct foo = (my_struct) (* arg); est incore essayez my_struct * foo = (mon_struct *) (arg); ET, dans la fonction Appelant le thread, assurez-vous qu'il soit statique (de sorte que la mémoire indiquée ne soit pas perdue dans le brouillard)

Questions connexes