Thursday, January 7, 2010

pthread_create memory leak?

After a hard work cleaning all the possible memory leaks in my application, I got stuck at the following error:


==24544== 144 bytes in 1 blocks are possibly lost in loss record 1 of 1
==24544== at 0x4023F5B: calloc (vg_replace_malloc.c:418)
==24544== by 0x40109AB: _dl_allocate_tls (dl-tls.c:300)
==24544== by 0x451F102: pthread_create@@GLIBC_2.1 (allocatestack.c:561)
==24544== by 0x451F5E7: pthread_create@GLIBC_2.0 (pthread_create.c:593)
==24544== by 0x424BC3C: Thread::start(void*) (threads.cpp:14)
==24544== by 0x425BB3F: startSocketListener(void*) (networkservice.cpp:161)
==24544== by 0x451E80D: start_thread (pthread_create.c:300)
==24544== by 0x44A17ED: clone (clone.S:130)



I double checked the code and everything works as intented, but the error was still there, some people wrote that this is not a "real" memory leak, because the pthread_create will reuse the allocated memory, but I was willing to get rid of this error, and get the message: "All heap blocks were freed -- no leaks are possible"

After googling I found that you could solve this adding the pthread_detach in order to free the used memory, so here's what I did:



Thread.cpp:

Thread::Thread(void *(*run)(void* arg)) {
runFunction = run;
}

void Thread::start(void* arg) {
int rc = pthread_create(&internal, NULL, runFunction, (void*)arg);
if (rc) {
cout << "Error creating the thread" << endl;
}
}

void Thread::join() {
pthread_join(internal, NULL);
}

Thread::~Thread() {
pthread_detach(internal);
}



Thread.h

class Thread {
private:
pthread_t internal;

public:
void *(*runFunction)(void* arg);

Thread(void *(*run)(void* arg));

~Thread();

void start(void* arg);

void join();
};



As you may noticed I left the detach call at the destructor, and now I don't have a single memory leak to be blame for.

1 comment:

  1. Yes, ran into this myself.

    pthread_detach() solved the "leak" in my case, where my app started a thread, but didn't care about the child's completion.

    Frustrating, cause I thought the leak was everywhere else :/ Lost stressful hours poking around in gdb/valgrind/insure doing memory dumps, etc.

    The man page for pthread_create() should really make it clear the parent thread maintains resources that need to be freed, similar to the open()/close() paradigm.

    It seems a parent thread interested in the child's completion should use pthread_join(), or otherwise use pthread_detach() if it doesn't care.

    I'd used pthreads many times previously, but always used pthread_join(). This one time the parent didn't need to join, so I just left it, not realizing pthread_detach() was needed to free the resources.

    ReplyDelete