2016-07-28 15 views
1

Die folgende Funktion funktioniert nicht. pin_thread_function erhalten manchmal Müll anstelle der Strukturdaten. Was ist falsch? Ich weiß, dass das ein grundsätzliches Problem ist, aber ich kann es nicht erklären.Wie übergeben Sie eine lokale Struktur als Parameter an pthread_create?

typedef void (*state_callback_t)(int state); 

struct pin_thread_params 
{ 
    char pin[3 + 1]; 
    state_callback_t callback_onchange; 
}; 

extern int pin_monitor_create(const char * pin, 
     state_callback_t callback_onchange) 
{ 
    int ret; 
    unsigned long int thread; 
    struct pin_thread_params params; 

    //Setup struct 
    strcpy(params.pin, "123"); 
    params.callback_onchange = callback_onchange; 

    //Create thread with struc as parameter 
    ret = pthread_create(&thread, NULL, pin_thread_function, &params); 
    if (!ret) 
    { 
     ret = pthread_detach(thread); 
    } 

    return ret; 
} 

static void * pin_thread_function(void * context) 
{ 
    struct pin_thread_params params; 
    memcpy(&params, context, sizeof(params)); 

    //Sometimes the correct string, most time garbage 
    printf("Started monitoring %s", params.pin); 
} 

Wenn params vor pthread_create malloc'ed ist alles in Ordnung, wie das funktioniert:

... 
    struct pin_thread_params * params; 

    //Setup struct with malloc 
    params = malloc(sizeof(struct pin_thread_params)); 
    strcpy(params->pin, "123"); 
    params->callback_onchange = callback_onchange; 
... 

Antwort

3

struct pin_thread_params params statisch zugeordnet ist und die Adresse ist nicht sicher zu benutzen, wenn der Umfang der es vorbei ist (das heißt, nachdem pin_monitor_create zurückgekehrt). Es kann vorkommen, dass die Thread-Ausführung manchmal startet, bevor die pin_monitor_create beendet wurde und Sie die gültigen Daten in params sehen. Der dynamisch zugewiesene Speicher stammt jedoch vom Heapspeicher und kann verwendet werden, bis Sie ihn freigeben. Daher erhalten Sie immer gültige Daten unter params innerhalb von pin_thread_function.

+0

Also 'params' ist verloren, gleich nach' pthread_create'. Ich war mir fast sicher, dass es erst am Ende der Funktion 'pin_monitor_create' verschwinden würde ... ;-(Fehle ich ein grundlegendes Scope-Konzept? – natenho

+0

Nein, lies was er nochmal geschrieben hat. Es ist am Ende von' pin_monitor_create verschwunden '. –

+1

@natenho Es ist nicht verloren nach' pthread_create', es ist verloren nach 'pin_monitor_create' Sie haben keine direkte Kontrolle über den Thread-Scheduler.Wenn der Haupt-Thread die Ausführung von' pin_thread_create' beendet, bevor der 'pin_thread_function'-Thread ausgeführt wird, haben Sie Wenn Sie Glück haben und der 'pin_thread_function'-Thread ausgeführt wird, bevor der Haupt-Thread fertig ist, sehen Sie Ihren String oder auf einem Multi-Core-Chip könnten die 2 Threads wirklich parallel laufen Sie müssen einige Methoden zur Thread-Synchronisierung verwenden. – yano

2

Ich bin nicht besonders gut informiert über pThreads (kann nur noch nicht ganz Kommentar), aber Sie geben einen Zeiger an den Stapelspeicher, der dem Thread zugewiesen wurde, der schließlich durch Ausführen von Funktionsaufrufen verfälscht wird.

+0

Sollen nicht params und der Stack bis zum Ende von pin_monitor_create leben? – natenho

+0

Parameter auf dem Stapel leben, bis Pin-Monitor-Erstellung vorbei ist mit. –

+0

Ja, aber Sie sind abhängig von pin_thread_function(), um die Kopie zu erstellen, bevor pin_monitor_create() beendet wird. Das ist der Grund warum man manchmal Müll bekommt und manchmal funktioniert es. Sie sind abhängig vom Scheduler. mallocing wäre der richtige Weg, damit umzugehen. – ktb