I have noticed that when I call a method using a thread in the form
////main code/////
pthread_t thread;
pthread_create(thread,function,data);
//////////////////
void* function(void* data){
//work with some data on the heap via a vector on the stack
std::vector<double> variable (100,1.2345);
//do contents of thread
pthread_exit(NULL);
}
despite having no calls to new
(except implicitly in vector variable) I get a memory leak with the amount of memory usage going linearly with the number of times I call function
in this way.
However if I do this
void* function(void* data){
{
std::vector<double> variable (100,1.2345);
//do contents of thread
}
pthread_exit(NULL);
}
the memory leak doesn't occur.
It seems that pthread_exit(NULL)
doesn't clear the stack variables like you would get at the end of a normal function with return
(I am correct about that right?!) so putting them within their own scope ensures they get freed.
However, this seems like a massive kludge. How do I ensure the stack variables (and their contents on the heap in terms of containers) are cleared properly when exiting a pthread?
It seems that pthread_exit(NULL)
doesn't clear the stack variables like you would get at the end of a normal function with return (I am correct about that right?!)
That's like calling exit(0)
in non-threaded code, the program exits right away and doesn't unwind the stack. (Since the pthreads spec is defined in terms of C, not C++, it doesn't define what happens with C++ destructors, so it's platform specific).
so putting them within their own scope ensures they get freed.
Because that way the vector's destructor runs before you call pthread_exit()
.
How do I ensure the stack variables (and their contents on the heap in terms of containers) are cleared properly when exiting a pthread?
Just return from the thread function, you don't need to use pthread_exit
to exit from the thread start function (the one that was passed to pthread_create
). POSIX says:
An implicit call to pthread_exit()
is made when a thread other than the thread in which main()
was first invoked returns from the start routine that was used to create it.
and the GNU/Linux man page says the same thing slightly differently:
Performing a return from the start function of any thread other than
the main thread results in an implicit call to pthread_exit()
, using
the function's return value as the thread's exit status.
You can use pthread_exit
to exit the thread from other functions further down the stack, just like you can use exit()
to quit a program instead of returning from main()
, but at the outermost function just return NULL;
(or whatever return value you want).
The only time using pthread_exit(x)
makes a difference to simply return x;
is in main
where it will cause the program to wait until other threads finish.
The calls to new()
are hidden in the std::vector<>
implementation.
In your first code sample pthread_exit(NULL);
will exit the thread, before the std::vector<>
destructor is called, thus the memory leaks.
Your second example forces the destructor of the std::vector<>
is called before pthread_exit(NULL);
.
(Okay, I can see that someone else addressed this issue already... And yes, this only applies to joinable threads. If you try to detach a non-joinable thread you raise an error.)
You'll need to call pthread_detach(...)
to configure the pthread for resource reclamation on exit.
pthread_detach documentation
This is not to invalidate any of the other answers. However, you'll need to detach any joinable child thread that you don't join, if you want its stack space to be reclaimed when it exits! Why would you ever not want that?
Even if you solve this particular leak with a code change, you'll need to move forward with this awareness if you are going to program with child threads in C/C++. std::thread
and boost::thread
have similar requirements.