2016-08-05 33 views
-1

Ich bin 32 bits von OS ausgeführt. Jetzt gibt der von mir erstellte Thread einen int-Wert zurück, der größer als 4G sein kann. Wie kann ich diesen Wert von meiner main() Funktion durch pthread_join() erhalten? Sieht aus wie in 32 bits System, (void *) ist 4 Bytes.Linux, C: Wie kann ich einen Rückgabewert von einem Thread erhalten, der größer als 4G in einem 32-Bit-Betriebssystem ist?

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

void* thread_function(void) 
{ 
    uint64_t nbytes = 0; 
    //assign values to nbytes, it could be larger than 4G. 
    return (void *)nbytes; 
} 

int main() 
{ 
    pthread_t thread_id; 
    uint64_t nbytes; 

    pthread_create (&thread_id, NULL, &thread_function, NULL); 
    pthread_join(thread_id,(void**)&nbytes); 
} 
+1

Warum senden Sie '& nbytes' nicht als Ihr NULL-Argument an' pthread_create' und einfach den Wert über die Adresse in Ihrer Funktion setzen und setzen? – WhozCraig

+4

Zuerst ist Ihre 'thread_function' vom falschen Typ. Es sollte Argumente brauchen. Jetzt rate mal was? Sie können diese Argumente verwenden, um Werte hin und her zu übergeben. Und der Rückgabetyp "void *" ist eigentlich nicht dazu bestimmt, an Nicht-Zeigertypen zu übergeben. –

Antwort

2

So:

void* thread_function(void *) 
{ 
    uint64_t nbytes = 0; 
    //assign values to nbytes, it could be larger than 4G. 

    void *retval = malloc (sizeof (nbytes)); 
    memcpy (retval, &nbytes, sizeof (nbytes)); 
    return retval; 
} 

int main() 
{ 
    pthread_t thread_id; 
    uint64_t nbytes; 

    pthread_create (&thread_id, NULL, &thread_function, NULL); 

    void *ret; 
    pthread_join(thread_id, &ret); 
    memcpy (nbytes, ret, sizeof (nbytes)); 
    free (ret); 
} 

Dies ist ein gemeinsames Muster für einen Wert von einem Thread zu einem anderen zu übertragen. Der sendende Thread weist Speicher zu, kopiert den Wert und übergibt einen Zeiger. Der empfangende Thread ruft den Zeiger ab, kopiert den Wert und gibt den Zeiger frei.

+0

Die 'thread_function'-Signatur ist ungültig. Als Alternative (und ich würde sagen, ein sicherer) Ansatz kann es einen Zeiger auf einen vorab zugewiesenen Puffer vom empfangenden Thread nehmen und es einfach füllen. Es ist eine viel bessere Praxis, den Zuteilungs- und Freigabekode auf derselben Ebene zu haben. –

+0

@EugeneSh. Danke, behoben. Dies ist ein sehr standardmäßiges Muster, weil es auch funktioniert, wenn der empfangende Thread keine Ahnung hat, wie groß das Objekt ist und selbst wenn das Erstellen und Verbinden des Threads an sehr unterschiedlichen Orten stattfindet. Ich denke, in diesem Fall ist es schlimmer, die Zuweisung an die Erstellung des Threads zu binden, da sie nicht logisch mit dem Ergebnisort verknüpft ist, an dem das Ergebnis erstellt oder verbraucht wird. –

+0

Nun, ja. Der Anwendungsfall der unbekannten Objektgröße ergibt einen perfekten Sinn. –

2

David Schwartz Lösung ist bekannt, aber ein bisschen zu viel, um eine einfache ganze Zahl zu übergeben; malloc() ist teuer und nicht unbedingt Thread-sicher (sehr unwahrscheinlich, aber mit all den eingebetteten Sachen heute & hellip;).

die Idee der ersten beiden commen zum OP Picking up (WhozCraig und Eugene Sh.)

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

void *thread_function(void *arg) 
{ 
    /* 
    No direct dereferencing 
     *arg = 0xdeadbeefcafe; 
    would give a compile error. With GCC it would be 

    threadargs.c:8:5: warning: dereferencing ‘void *’ pointer [enabled by default] 

    */ 
    uint64_t *nbytes = arg; 
    *nbytes = 0xdeadbeefcafe; 
    // you can return a simple status here, for example an error 
    return 0; 
} 

int main() 
{ 
    pthread_t thread_id; 
    uint64_t nbytes; 

    pthread_create(&thread_id, NULL, &thread_function, &nbytes); 
    pthread_join(thread_id, NULL); 
#define __STDC_FORMAT_MACROS 
#include <inttypes.h> 
    printf("nbytes = %" PRIx64 "\n", nbytes); 

    return 0; 
} 

sollte die Arbeit in einer anderen Art und Weise tun, vielleicht eine bessere für diese Art der Nutzung.

Nachteil: jeder Thread möchte seine eigene Variable füllen, so ist es besser für eine feste, kleine Menge von Threads passen, sonst Sie aus dem Haufen zuweisen und nichts gewonnen haben, genau das Gegenteil: es wäre mehr kompliziert, alle malloc()/free() zu halten. David Schwartz Methode wäre in diesem Fall viel geeigneter.

+0

Wenn Sie POSIX-Threads verwenden, ist 'malloc()' threadsicher. –

+0

Auch GlibC> = 2.2 (zumindest denke ich noch früher), aber ich wurde zu oft verbrannt, um keinen Hinweis darauf zu geben, "besser zuerst zu überprüfen, egal wie sicher Sie sind". – deamentiaemundi