2013-07-14 13 views
15

Leck verursacht Immer wenn ich ein pthread schaffen, valgrind gibt ein Speicherleck,warum Pthread ein Speicher

Zum Beispiel die folgenden Code:

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

void *timer1_function (void *eit){ 
    (void) eit; 
    printf("hello world\n"); 
    pthread_exit(NULL); 
} 

int main(void){ 
    pthread_t timer1; 
    pthread_create(&timer1, NULL, timer1_function, NULL); ///////line13 
    int i=0; 
    for(i=0;i<2;i++){usleep(1);} 
    return 0; 
} 

valgrind Ausgänge

==1395== HEAP SUMMARY: 
==1395==  in use at exit: 136 bytes in 1 blocks 
==1395== total heap usage: 6 allocs, 5 frees, 1,134 bytes allocated 
==1395== 
==1395== 136 bytes in 1 blocks are possibly lost in loss record 1 of 1 
==1395== at 0x402A629: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==1395== by 0x4011304: allocate_dtv (dl-tls.c:297) 
==1395== by 0x4011AAB: _dl_allocate_tls (dl-tls.c:461) 
==1395== by 0x4052470: [email protected]@GLIBC_2.1 (allocatestack.c:571) 
==1395== by 0x8048566: main (test.c:13) 
==1395== 
==1395== LEAK SUMMARY: 
==1395== definitely lost: 0 bytes in 0 blocks 
==1395== indirectly lost: 0 bytes in 0 blocks 
==1395==  possibly lost: 136 bytes in 1 blocks 
==1395== still reachable: 0 bytes in 0 blocks 
==1395==   suppressed: 0 bytes in 0 blocks 

warum pthread_create Ursache ein Problem, obwohl ich die Manpage als Referenz benutzte, und wie kann ich das beheben?

+0

mögliche Duplikate von [Valgrind Memory Leck Fehler bei der Verwendung von Pthread \ _create] (http: // Stackoverflow.com/questions/5610677/valgrind-memory-leak-errors-wenn-using-pthread-create) – nos

Antwort

22

Ein Thread ist eine zugewiesene Ressource und Sie haben es nicht frei vor dem Verlassen. Sie sollten pthread_join anrufen; Dies würde auch die Notwendigkeit für Ihre hackish und falsche Schlafschleife beseitigen.

Es ist möglich, dass, selbst wenn Sie dies beheben, Valgrind immer noch ein "Leck" sehen wird, da einige Implementierungen von POSIX-Threads (ich vermute, Sie glibc/NPTL verwenden) Thread-Ressourcen Cache und wiederverwenden, anstatt sie zu befreien völlig. Ich bin mir nicht sicher, ob Valgrind darum geht oder nicht.

+1

+1. Ich denke, Ihr zweiter Absatz erklärt, warum ich den Unterdrückungs-Ansatz in meiner Antwort so oft gesehen habe. – simonc

+0

Alternative zu Pthread_join: Verwenden Sie Pthread_detach, aber das Speicherleck bleibt. – Aubin

4

Ich glaube, dass valgrind analysiert den Zustand Ihres Programms zum Zeitpunkt der Beendigung, die wahrscheinlich ist, bevor der Thread seine Ausführung beendet: zwei Mikrosekunden möglicherweise nicht genug, um "Hello, world!\n" zu Konsole schreiben. Hinzufügen eines Anrufs zu pthread_join sollte dieses Leck beheben:

pthread_join(timer1, NULL); 
+3

Sie können einfach einen Nullzeiger für das zweite Argument statt einen Zeiger auf eine Dummy-Variable übergeben. –

+0

@R .. Ja, ich denke du hast Recht ... OP 'NULL' zu 'pthread_exit' übergeben, so 'Pthread_join' könnte auch das Ergebnis explizit ignorieren. Vielen Dank! – dasblinkenlight

0

Speicherverlust ist ein Ergebnis der Tatsache, dass der entsprechende dynamisch zugewiesene Speicher nicht freigegeben wird, wenn der Thread ohne Abbruch ausgeführt wird. Verwenden Sie pthread_cancel() zusammen mit pthread_cleanup_push (CleanupHandler, NULL) und pthread_cleanup_pop (0), um die Thread-Bereinigung nach dem Abbrechen durchzuführen.

1

Ich habe ähnliche Ergebnisse gesehen, wenn ich pthread_join nicht aufrufen kann.

Wenn ich pthread_join aufrufen, zeigt Valgrind keine Speicherfehler oder Lecks an. Ich habe ein sauberes Ergebnis mit pthread_kill erhalten, um zu sehen, ob der Thread noch existiert, und dann den Join aufzurufen, um Ressourcen aufzuräumen und freizugeben.

int 
stop_worker(worker_t *self) 
{ 
    if (self) { 
     // signal the thread to quit 
      // (here using a variable and semaphore) 
     self->thread_quit=TRUE; 
     sem_post(&self->sem); 

     // wait for it to stop 
     // (could use counter, etc. to limit wait) 
     int test=0; 
     while (pthread_kill(self->thread,0) == 0) { 
      MDEBUG(MD_XF_LOGGER,"waiting for thread to exit...\n",test); 
      delay_msec(50); 
     } 

     // even though thread is finished, need to call join 
     // otherwise, it will not release its memory (and valgrind indicates a leak) 
     test=pthread_join(self->thread,NULL); 
     return 0;   
    } 
    return -1; 
} 
0

Das Leck, das an den DTV (Dynamic Thema Vector) Struktur im Zusammenhang auftaucht, die in dem untergeordneten Thread lokalen Speicher (tls) zugeordnet ist.

Die Verwendung von pthread_join() im Haupt-Thread (d. H. Der Thread, der das Kind hervorgebracht hat) stellt sicher, dass das Leck behoben wird. Für Anwendungsfälle, in denen pthread_join() kein Anruf erforderlich ist, ruft der Aufruf pthread_detach mit Kind pthread_t sicher, dass der Speicher freigegeben wird.

Von Menschen für pthread_detach:

Die pthread_detach() Funktion markiert das durch Gewinde identifiziert Gewinde als abgelöst. Wenn ein losgelöster Thread beendet wird, werden seine Ressourcen automatisch wieder zum System freigegeben, ohne dass ein anderer Thread dem abgeschlossenen Thread beitreten muss.