Anzeige:
Ergebnis 1 bis 3 von 3

Thema: pthread_join gibt Speicher nicht frei

  1. #1
    Registrierter Benutzer
    Registriert seit
    24.06.2004
    Beiträge
    101

    pthread_join gibt Speicher nicht frei

    Hallo,

    ich rätsel schon seit geraumer Zeit an diesem Problem, und bin mit Sicherheit bereits betriebsblind. Kann mir jemand sagen, was an dem Code falsch sein soll, dass der Speicher mit pthread_join() nicht freigegeben wird?

    Code:
    /*
     * main.c
     */
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <string>
    
    #define OWNPID getpid()
    #define MAXTHREADS 10
    
    struct threadargs
    {
    	unsigned int id;
    	std::string first;
    	std::string last;
    };
    
    void *threadfunc(void *args)
    {
    	threadargs *myArgs = (threadargs*)args;
    	printf("first: %s\n", myArgs->first.c_str());
    	printf("last: %s\n", myArgs->last.c_str());
    
    	pthread_exit((void*)0);
    }
    
    void TraceUsage(char *label)
    {
    	pid_t pid;
    	char comm[30];
    	char state;
    	pid_t ppid;
    	gid_t pgrp;
    	int session;
    	int tty;
    	gid_t tpgid;
    	unsigned int flags;
    	unsigned long minflt;
    	unsigned long cminflt;
    	unsigned long majflt;
    	unsigned long cmajflt;
    	int utime;
    	int stime;
    	int cutime;
    	int cstime;
    	int counter;
    	short priority;
    	unsigned long timeout;
    	unsigned long itrealvalue;
    	int starttime;
    	unsigned long vsize;
    	unsigned long rss;
    	unsigned long rlim;
    	unsigned long startcode;
    	unsigned long endcode;
    	unsigned long startstack;
    	unsigned long kstkesp;
    	unsigned long kstkeip;
    	int signal;
    	int blocked;
    	int sigignore;
    	int sigcatch;
    	unsigned long wchan;
    
    	char statpath[30];
    
    	sprintf(statpath, "/proc/%d/stat", OWNPID);
    	FILE *fp = fopen(statpath, "r");
    
    	if(fp == NULL)
    		return;
    
    	int r = fscanf(fp,
    		"%d %s %c %d %d %d %d %d %u %ld %ld %ld %ld %d %d %d %d %d %d %ld %ld %d %ld %ld %ld %ld %ld %ld %ld %ld %d %d %d %d %ld",
    		&pid, comm, &state, &ppid, &pgrp, &session, &tty, &tpgid, &flags, &minflt, &cminflt,
    		&majflt, &cmajflt, &utime, &stime, &cutime, &cstime, &counter, &priority, &timeout,
    		&itrealvalue, &starttime, &vsize, &rss, &rlim, &startcode, &endcode, &startstack,
    		&kstkesp, &kstkeip, &signal, &blocked, &sigignore, &sigcatch, &wchan
    	);
    
    	fclose(fp);
    
    	if(r == 0)
    	{
    		return;
    	}
    
    	fprintf(stderr, "%s: rss = %ld, vsize = %ld\n\n", label, rss, vsize);
    }
    
    int main(void)
    {
    	pthread_t thread[MAXTHREADS];
    	char label[10];
    	unsigned int i;
    	threadargs targs;
    	targs.first = "Hello";
    	targs.last = "World!";
    
    	TraceUsage("Init");
    
    	for(i = 0; i < MAXTHREADS; i++)
    	{
    		targs.id = i;
    		pthread_create(&thread[i], NULL, threadfunc, (void*)&targs);
    		pthread_join(thread[i], NULL);
    		sprintf(label, "%d", i);
    		TraceUsage(label);
    	}
    }
    Es wird folgende Ausgabe erzeugt:

    Code:
    ./threadtest
    Init: rss = 220, vsize = 2375680
     
    first: Hello
    last: World!
    0: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    1: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    2: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    3: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    4: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    5: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    6: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    7: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    8: rss = 234, vsize = 10780672
     
    first: Hello
    last: World!
    9: rss = 234, vsize = 10780672
    Wäre toll, wenn mir da jemand weiter helfen könnte.

    PS: Ja, ich weiß, man soll C++ Objekte nicht in C-Code einbauen, das war auch nur ein Test, um den Speicher künstlich aufzublähen.

  2. #2
    Registrierter Benutzer
    Registriert seit
    23.12.2005
    Beiträge
    16
    Zitat Zitat von Beatkiller Beitrag anzeigen
    Hallo,

    ich rätsel schon seit geraumer Zeit an diesem Problem, und bin mit Sicherheit bereits betriebsblind. Kann mir jemand sagen, was an dem Code falsch sein soll, dass der Speicher mit pthread_join() nicht freigegeben wird?
    Welcher Speicher soll denn freigegeben werden? pthread_join() wartet, dass ein gegebener Thread beendet wird, sonst nichts. Abgesehen davon benutzt Du pthread_create() und pthread_join() in ziemlich sinnloser Weise: Du erzeugst in Deiner Schlaufe immer einen Thread und wartest sofort danach, dass dieser Thread beendet wird. Das heisst, in Deinem Programm existieren immer nur maximal zwei Threads gleichzeitig. Damit Du 10 Threads gleichzeitig erhältst, musst Du in der ersten Schlaufe die Threads erzeugen und in einer zweiten Schlaufe darauf warten, dass die Threads beendet sind.

  3. #3
    Registrierter Benutzer
    Registriert seit
    24.06.2004
    Beiträge
    101
    Danke für die Antwort. Ich bin mir im Klaren darüber, dass ich nur einen Kind-Thread habe plus Haupt-Thread. Das war für diesen Proof-of-concept auch genau mein Ziel. Meine Frage war an dieser Stelle, warum der vsize (siehe Ausgabe) nicht zurück auf 2375680 fällt, nach ich mit pthread_join() auf das Ende des Kind-Threads gewartet habe. Das bei Neu-Erzeugung eines Kind-Threads mittels pthread_create() dann kein neuer Speicher angefordert wird, ist ja schon mal was, weil es bedeutet, das der gleiche Speicherbereich für alle Kind-Threads verwendet wird. Ich hätte allerdings erwartet, das nach Beenden des Threads auch der Stack für den Thread freigegeben wird, was offensichtlich nicht der Fall ist.

    Ich habe auch schon mit pthread_attr_setdetachstate() den Thread auf PTHREAD_CREATE_DETACHED gesetzt, aber das führt zum gleichen Resultat.

    Eine andere Sache ist die Analyse mittels Valgrind oder memprof:

    Code:
    ==12691== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from 1)
    --12691--
    --12691-- supp:     21 Ubuntu-stripped-ld.so
    ==12691== malloc/free: in use at exit: 68 bytes in 1 blocks.
    ==12691== malloc/free: 12 allocs, 11 frees, 3,940 bytes allocated.
    ==12691==
    ==12691== searching for pointers to 1 not-freed blocks.
    ==12691== checked 8,511,296 bytes.
    ==12691==
    ==12691== 68 bytes in 1 blocks are possibly lost in loss record 1 of 1
    ==12691==    at 0x401BEF5: calloc (vg_replace_malloc.c:397)
    ==12691==    by 0x400EDAB: _dl_allocate_tls (in /lib/ld-2.3.2.so)
    ==12691==    by 0x402C8CA: allocate_stack (in /lib/tls/libpthread-0.34.so)
    ==12691==    by 0x402C587: pthread_create@@GLIBC_2.1 (in /lib/tls/libpthread-0.34.so)
    ==12691==    by 0x804894C: main (main.cpp:112)
    ==12691==
    ==12691== LEAK SUMMARY:
    ==12691==    definitely lost: 0 bytes in 0 blocks.
    ==12691==      possibly lost: 68 bytes in 1 blocks.
    ==12691==    still reachable: 0 bytes in 0 blocks.
    ==12691==         suppressed: 0 bytes in 0 blocks.
    --12691--  memcheck: sanity checks: 2 cheap, 2 expensive
    --12691--  memcheck: auxmaps: 0 auxmap entries (0k, 0M) in use
    --12691--  memcheck: auxmaps_L1: 0 searches, 0 cmps, ratio 0:10
    --12691--  memcheck: auxmaps_L2: 0 searches, 0 nodes
    --12691--  memcheck: SMs: n_issued      = 12 (192k, 0M)
    --12691--  memcheck: SMs: n_deissued    = 0 (0k, 0M)
    --12691--  memcheck: SMs: max_noaccess  = 65535 (1048560k, 1023M)
    --12691--  memcheck: SMs: max_undefined = 0 (0k, 0M)
    --12691--  memcheck: SMs: max_defined   = 158 (2528k, 2M)
    --12691--  memcheck: SMs: max_non_DSM   = 12 (192k, 0M)
    --12691--  memcheck: max sec V bit nodes:    1 (0k, 0M)
    --12691--  memcheck: set_sec_vbits8 calls: 1 (new: 1, updates: 0)
    --12691--  memcheck: max shadow mem size:   496k, 0M
    --12691-- translate:            fast SP updates identified: 3,386 ( 87.6%)
    --12691-- translate:   generic_known SP updates identified: 234 (  6.0%)
    --12691-- translate: generic_unknown SP updates identified: 244 (  6.3%)
    --12691--     tt/tc: 6,608 tt lookups requiring 6,777 probes
    --12691--     tt/tc: 6,608 fast-cache updates, 3 flushes
    --12691--  transtab: new        3,130 (67,253 -> 948,035; ratio 140:10) [0 scs]
    --12691--  transtab: dumped     0 (0 -> ??)
    --12691--  transtab: discarded  6 (153 -> ??)
    --12691-- scheduler: 337,679 jumps (bb entries).
    --12691-- scheduler: 2/3,710 major/minor sched events.
    --12691--    sanity: 3 cheap, 2 expensive checks.
    --12691--    exectx: 769 lists, 11 contexts (avg 0 per list)
    --12691--    exectx: 44 searches, 33 full compares (750 per 1000)
    --12691--    exectx: 0 cmp2, 46 cmp4, 0 cmpAll
    --12691--  errormgr: 7 supplist searches, 69 comparisons during search
    --12691--  errormgr: 21 errlist searches, 46 comparisons during search
    Besonders der non-freed pointer, der in _dl_allocate_tls() erzeugt wird, macht mich etwas stutzig. Was läuft hier falsch? Ist in pthread_create ein memory leak? Google führt mich auch nur zu Seiten, wo diese Thematik behandelt aber nicht vollständig geklärt wird. Arbeitet der Memory-Profiler hier fehlerhaft?

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •