Wiele argumentów funkcji wywoływanej przez pthread_create ()?

96

Muszę przekazać wiele argumentów do funkcji, którą chciałbym wywołać w osobnym wątku. Mam przeczytać , że typowy sposób, aby to zrobić, aby zdefiniować struct, zdać funkcję wskaźnika do tego, i wyłuskanie go do argumentów. Jednak nie mogę sprawić, żeby to zadziałało:

#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 */
}

Wynik tego powinien być:

5
7

Ale kiedy go uruchamiam, faktycznie otrzymuję:

141921115
-1947974263

Czy ktoś wie, co robię źle?

Michał
źródło
2
spróbować ulokować go na stercie?
Carson Myers,
1
@Carson Dlaczego to powinno mieć znaczenie?
sigjuice
5
Twoja struktura powinna żyć co najmniej tak długo, jak twój wątek. Jeśli tworzysz wątek i powracasz z funkcji o nazwie pthread_create (), struktura przydzielona na stosie może zostać nadpisana przez inne dane i może spowodować problemy w funkcji wątku. W tym przykładzie nie stanowi to problemu, ponieważ tworzący wątek czeka na zakończenie wątku roboczego przed zwróceniem.
Commodore Jaeger
@Commodore Jaeger Oh! Dziękuję, to jest problem, który miałem z drugim, z którym pracowałem. Naprawiłem to, umieszczając go na stercie za pomocą malloc (), jak powiedział Carson. To ma teraz dużo więcej sensu.
Michael,

Odpowiedzi:

78

Ponieważ mówisz

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

zamiast

struct arg_struct *args = arguments;

sigjuice
źródło
5
@sigjuice, to nie działa dla mnie. Widzę błąd kompilacji: nieprawidłowa konwersja z „void *” na „arg_struct *”.
Neshta
20

posługiwać się

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

zamiast

struct arg_struct *args = (struct arg_struct *)args;
Akash Agrawal
źródło
4

main()ma swój własny wątek i zmienne stosu. albo przydziel pamięć dla „args” w stercie, albo uczyń ją globalną:

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

//declares args as global out of main()

Następnie oczywiście zmień odniesienia z args->arg1na args.arg1itd.

Plamen Panov
źródło
2

Posługiwać się:

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

I przekaż te argumenty w ten sposób:

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

Nie zapomnij o darmowych argumentach! ;)

Elham
źródło
1

Argumenty funkcji print_the_arguments to argumenty, więc powinieneś użyć:

struct arg_struct *args = (struct arg_struct *)arguments. 
Stone.Carton
źródło
1
struct arg_struct *args = (struct arg_struct *)args;

-> to przypisanie jest błędne, mam na myśli argument zmiennej powinien być używany w tym kontekście. Twoje zdrowie!!!

Jashmikant
źródło
1

Podczas tworzenia wątku tego kodu przekazywany jest adres wskaźnika funkcji. Oryginalny pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

Powinien brzmieć jako pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

Dobrym sposobem na zapamiętanie jest to, że wszystkie argumenty tej funkcji powinny być adresami.

some_threadjest deklarowana statycznie, więc adres jest wysyłany poprawnie za pomocą &.

Utworzyłbym pthread_attr_tzmienną, następnie użyłbym pthread_attr_init()jej i przekazał adres tej zmiennej. Ale przekazanie NULLwskaźnika jest również prawidłowe.

Przyczyną &problemu jest tutaj przed etykietą funkcji. Użyta etykieta jest już przypisana void*do funkcji, więc wymagana jest tylko etykieta.

Powiedzenie != 0za pomocą ostatniego argumentu wydaje się powodować nieokreślone zachowanie. Dodanie tego oznacza, że ​​zamiast referencji przekazywana jest wartość logiczna.

Odpowiedź Akasha Agrawala jest również częścią rozwiązania problemu tego kodu.

Rayshaun Preston
źródło
1

Mam to samo pytanie, co przy oryginalnym plakacie, Michael.

Jednak bez powodzenia próbowałem zastosować przesłane odpowiedzi do oryginalnego kodu

Po kilku próbach i błędach, oto moja wersja kodu, która działa (lub przynajmniej działa dla mnie!). A jeśli przyjrzysz się uważnie, zauważysz, że różni się on od wcześniej opublikowanych rozwiązań.

#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 */
}
VeeDub
źródło