Whenever I create a pthread, valgrind outputs a memory leak,
For example the below 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 outputs
==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: pthread_create@@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
why pthread_create cause a problem although I was using the man page as reference, and how can I fix it?
A thread is an allocated resource and you did not free it before exiting. You should call pthread_join
; this would also eliminate the need for your hackish and incorrect sleep loop.
It's possible that even once you fix this, valgrind will still see a "leak", since some implementations of POSIX threads (I'm guessing you're using glibc/NPTL) cache and reuse thread resources rather than freeing them fully. I'm not sure if valgrind works around this or not.
I think that valgrind
analyzes the state of your program at the time it exits, which is likely before the thread finishes its execution: two microseconds may not be enough to write "Hello, world!\n"
to console. Adding a call to pthread_join
should fix this leak:
pthread_join(timer1, NULL);
I've seen similar results when I fail to call pthread_join.
When I do call pthread_join, Valgrind will indicate no memory errors or leaks. I've had a clean result using pthread_kill to see if the thread still exists, then calling join to clean up and release resources.
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;
}
The leak that shows up is related to the DTV (Dynamic Thread Vector) structure that is allocated in the child thread's local storage (tls).
Using pthread_join()
in the main thread (i.e. the thread that spawned the child) will ensure to fix the leak.
For use cases where pthread_join()
call is not required, calling pthread_detach
with child pthread_t ensures the memory is released.
From man for pthread_detach
:
The pthread_detach()
function marks the thread identified by thread
as detached. When a detached thread terminates, its resources are
automatically released back to the system without the need for
another thread to join with the terminated thread.
memory leak is a result of the fact that if the thread is left running without cancellation , then the corresponding dynamically allocated memory is not freed. Use pthread_cancel() along with pthread_cleanup_push(CleanupHandler, NULL) and pthread_cleanup_pop(0) to do the thread cleanup after cancellation.