Mehrere von pthread_create () aufgerufene Funktionsargumente?

93

Ich muss mehrere Argumente an eine Funktion übergeben, die ich in einem separaten Thread aufrufen möchte. Ich habe gelesen, dass der typische Weg, dies zu tun, darin besteht, eine Struktur zu definieren, der Funktion einen Zeiger darauf zu übergeben und sie für die Argumente zu dereferenzieren. Ich kann dies jedoch nicht zum Laufen bringen:

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

Die Ausgabe hierfür sollte sein:

5
7

Aber wenn ich es laufen lasse, bekomme ich tatsächlich:

141921115
-1947974263

Weiß jemand was ich falsch mache?

Michael
quelle
2
versuchen Sie es auf dem Haufen zuzuweisen?
Carson Myers
1
@Carson Warum sollte das einen Unterschied machen?
Sigjuice
5
Ihre Struktur sollte mindestens so lange leben wie Ihr Thread. Wenn Sie einen Thread erstellen und von der Funktion mit dem Namen pthread_create () zurückkehren, wird die auf dem Stapel zugewiesene Struktur möglicherweise von anderen Daten überschrieben und kann zu Problemen in Ihrer Thread-Funktion führen. In diesem Beispiel ist dies kein Problem, da der erstellende Thread darauf wartet, dass der Arbeitsthread abgeschlossen ist, bevor er zurückkehrt.
Commodore Jaeger
@Commodore Jaeger Oh! Danke, das ist das Problem, das ich mit dem anderen hatte, mit dem ich gearbeitet habe. Ich habe es behoben, indem ich es mit malloc () auf dem Haufen zugewiesen habe, wie Carson sagte. Das macht jetzt viel mehr Sinn.
Michael

Antworten:

77

Denn du sagst

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

anstatt

struct arg_struct *args = arguments;

Sigjuice
quelle
4
@ Sigjuice, es funktioniert nicht bei mir. Ich sehe einen Kompilierungsfehler: Ungültige Konvertierung von 'void *' nach 'arg_struct *'.
Neshta
20

verwenden

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

anstelle von

struct arg_struct *args = (struct arg_struct *)args;
Akash Agrawal
quelle
4

main()hat seine eigenen Thread- und Stack-Variablen. Ordnen Sie entweder Speicher für 'args' im Heap zu oder machen Sie ihn global:

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

//declares args as global out of main()

Dann ändern Sie natürlich die Referenzen von args->arg1zu args.arg1etc ..

Plamen Panov
quelle
2

Verwenden:

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

Und übergeben Sie diese Argumente wie folgt:

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

Vergiss die freien Argumente nicht! ;)

Elham
quelle
1

Die Argumente von print_the_arguments sind Argumente, daher sollten Sie Folgendes verwenden:

struct arg_struct *args = (struct arg_struct *)arguments. 
Stone.Carton
quelle
1
struct arg_struct *args = (struct arg_struct *)args;

-> Diese Zuordnung ist falsch, ich meine, das variable Argument sollte in diesem Zusammenhang verwendet werden. Prost!!!

Jashmikant
quelle
1

Bei der Thread-Erstellung dieses Codes wird die Adresse eines Funktionszeigers übergeben. Das Original pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0

Es sollte lauten wie pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)

Eine gute Möglichkeit, sich daran zu erinnern, ist, dass alle Argumente dieser Funktion Adressen sein sollten.

some_threadwird statisch deklariert, sodass die Adresse ordnungsgemäß mit gesendet wird &.

Ich würde eine pthread_attr_tVariable erstellen , sie dann verwenden pthread_attr_init()und die Adresse dieser Variablen übergeben. Das Übergeben eines NULLZeigers ist jedoch ebenfalls gültig.

Das &vor dem Funktionsetikett liegende Problem verursacht hier das Problem. Das verwendete Label ist bereits eine void*Funktion, daher ist nur das Label erforderlich.

!= 0Mit dem letzten Argument zu sagen, scheint unbestimmtes Verhalten zu verursachen. Wenn Sie dies hinzufügen, wird anstelle einer Referenz ein Boolescher Wert übergeben.

Die Antwort von Akash Agrawal ist auch Teil der Lösung des Problems dieses Codes.

Rayshaun Preston
quelle