Più argomenti per una funzione chiamata da pthread_create ()?


93

Ho bisogno di passare più argomenti a una funzione che vorrei chiamare su un thread separato. Ho letto che il modo tipico per farlo è definire una struttura, passare alla funzione un puntatore a quella e dereferenziarla per gli argomenti. Tuttavia, non riesco a farlo funzionare:

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

struct arg_struct {
    int arg1;
    int arg2;
};

void *print_the_arguments(void *arguments)
{
    struct arg_struct *args = (struct arg_struct *)args;
    printf("%d\n", args -> arg1);
    printf("%d\n", args -> arg2);
    pthread_exit(NULL);
    return NULL;
}

int main()
{
    pthread_t some_thread;
    struct arg_struct args;
    args.arg1 = 5;
    args.arg2 = 7;

    if (pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0) {
        printf("Uh-oh!\n");
        return -1;
    }

    return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}

L'output per questo dovrebbe essere:

5
7

Ma quando lo eseguo ottengo effettivamente:

141921115
-1947974263

Qualcuno sa cosa sto sbagliando?


2
provare ad allocarlo sull'heap?
Carson Myers

1
@Carson Perché dovrebbe fare la differenza?
sigjuice

5
La tua struttura dovrebbe vivere almeno quanto il tuo thread. Se stai creando un thread e ritorni dalla funzione che ha chiamato pthread_create (), la struttura allocata sullo stack potrebbe essere sovrascritta da altri dati e potrebbe causare problemi nella funzione thread. In questo esempio, non è un problema, poiché il thread di creazione attende il completamento del thread di lavoro prima di tornare.
Commodore Jaeger

@ Commodore Jaeger Oh! Grazie, questo è il problema che stavo avendo con l'altro con cui stavo lavorando. L'ho risolto allocandolo sull'heap usando malloc (), come ha detto Carson. Adesso ha molto più senso.
Michael il

Risposte:


77

Perchè tu dici

struct arg_struct *args = (struct arg_struct *)args;

invece di

struct arg_struct *args = arguments;


4
@sigjuice, non funziona per me. Vedo un errore di compilazione: conversione non valida da "void *" a "arg_struct *".
Neshta

20

uso

struct arg_struct *args = (struct arg_struct *)arguments;

al posto di

struct arg_struct *args = (struct arg_struct *)args;

4

main()ha il proprio thread e le variabili di stack. alloca memoria per 'args' nell'heap o rendilo globale:

struct arg_struct {
    int arg1;
    int arg2;
}args;

//declares args as global out of main()

Poi ovviamente cambia i riferimenti da args->arg1a args.arg1ecc.


2

Uso:

struct arg_struct *args = malloc(sizeof(struct arg_struct));

E passa questi argomenti in questo modo:

pthread_create(&tr, NULL, print_the_arguments, (void *)args);

Non dimenticare gli argomenti gratuiti! ;)


1

Gli argomenti di print_the_arguments sono argomenti, quindi dovresti usare:

struct arg_struct *args = (struct arg_struct *)arguments. 

1
struct arg_struct *args = (struct arg_struct *)args;

-> questa assegnazione è sbagliata, voglio dire che l'argomento della variabile dovrebbe essere usato in questo contesto. Saluti!!!


1

Nella creazione del thread di questo codice, viene passato l'indirizzo di un puntatore a funzione. L'originale pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

Dovrebbe essere letto come pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

Un buon modo per ricordare è che tutti gli argomenti di questa funzione dovrebbero essere indirizzi.

some_threadè dichiarato staticamente, quindi l'indirizzo viene inviato correttamente utilizzando &.

Creerei una pthread_attr_tvariabile, quindi la userei pthread_attr_init()e passerei l'indirizzo di quella variabile. Ma anche il passaggio di un NULLpuntatore è valido.

La parte &anteriore dell'etichetta della funzione è ciò che sta causando il problema qui. L'etichetta utilizzata è già una void*per una funzione, quindi è necessaria solo l'etichetta.

Dire != 0con l'argomento finale sembrerebbe causare un comportamento indeterminato. L'aggiunta di questo significa che viene passato un booleano invece di un riferimento.

Anche la risposta di Akash Agrawal fa parte della soluzione al problema di questo codice.


1

Ho la stessa domanda del poster originale, Michael.

Tuttavia ho provato ad applicare le risposte inviate per il codice originale senza successo

Dopo alcuni tentativi ed errori, ecco la mia versione del codice che funziona (o almeno funziona per me!). E se guardi da vicino, noterai che è diverso dalle soluzioni precedenti pubblicate.

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

struct arg_struct
{
   int arg1;
   int arg2;
} *args;

void *print_the_arguments(void *arguments)
{
   struct arg_struct *args = arguments;
   printf("Thread\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   pthread_exit(NULL);
   return NULL;
}

int main()
{
   pthread_t some_thread;
   args = malloc(sizeof(struct arg_struct) * 1);

   args->arg1 = 5;
   args->arg2 = 7;

   printf("Before\n");
   printf("%d\n", args->arg1);
   printf("%d\n", args->arg2);
   printf("\n");


   if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
   {
      printf("Uh-oh!\n");
      return -1;
   }

   return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.