Page 1 of 1
C++ local stack allocated instance destructor
Posted: Sat May 25, 2013 5:32 pm
by hazelnusse
If I allocate an instance of a C++ class type on the stack inside of a thread function, it seems like the destructor for this instance will not be executed if the thread function calls chThdExit() instead of actually returning. The compiler won't know that the no instructions will be executed after chThdExit() so presumably all the destructor calls for locals won't be called. I can use a scope block to force the destructor to run, or I can put all my functionality inside of another function that does return and hence all the destructors of local stack objects will be called before returning.
The documentation writes:
a thread terminates by returning from its top level function or invoking a specific API
So presumably returning from my top level function or calling chThdExit() will both work equivalently? If I return instead of calling chThdExit(), does the return value the same meaning as the parameter passed to chThdExit()?
Thanks,
Luke
Re: C++ local stack allocated instance destructor
Posted: Sat May 25, 2013 5:39 pm
by Giovanni
Hi,
Returning from a function is the same of calling chThdExit(), the parameter is the same of return value.
Giovanni
Re: C++ local stack allocated instance destructor
Posted: Mon May 27, 2013 10:20 pm
by hazelnusse
If chThdExit() never returns, and the compiler doesn't know this (which it seems like it will not), doesn't this imply that the cleanup code for user defined types (i.e., class destructors) will not be run, since the compiler implicitly places this code at the end the function body? So
vs.
would only be the same if all the local variables of the thread function have no destructor, i.e., built-in types or types which don't need to do anything special to clean up after themselves.
Specifically, here is a trivial made up example of what I am talking about:
Code: Select all
class foo {
public:
foo(int N) : data_ptr(new int[N]) {}
~foo() { delete [] data_ptr; }
private:
int * data_ptr;
};
msg_t thread_func(void *)
{
foo f(10);
chThdExit(0); /* Never returns, hence ~foo() is never called, hence memory leak of 10 ints on free store */
/* Code is placed implicitly here by the compiler to call ~foo(); but will never be executed because chThdExit never returns. */
}
if the call to chThdExit(0); was changed to return 0; then the implicit compiler generated calls to the destructor will be called and the memory will not be leaked. I'm not actually using new in my particular application, but I have some other cleanup code that needs to be called when a variable goes out of scope so I am pretty sure I need to use return, not chThdExit();
If I am missing something, let me know.
Luke
Re: C++ local stack allocated instance destructor
Posted: Mon May 27, 2013 10:34 pm
by Giovanni
Hi,
chThdExit() is equivalent to return but this does not include finalization code of course. I don't know any portable way to inform the compiler that the function does not actually return.
There are GCC extensions that allow to do that but I would not rely on those.
Giovanni
Re: C++ local stack allocated instance destructor
Posted: Tue May 28, 2013 3:03 am
by hazelnusse
chThdExit() is equivalent to return but this does not include finalization code of course.
To me this means they are not equivalent. Equivalent would mean the exact same cpu instructions will be executed, but since destructors will not be called when using chThdExit(), the code with return will take a different path than the code with chThdExit(). Of course, this only applies to threads implemented in C++ which declare objects on the stack that have a non-trivial destructor.
Re: C++ local stack allocated instance destructor
Posted: Tue May 28, 2013 11:06 pm
by MartinP
Some extra braces
{ ... } should do the job in c++
Code: Select all
msg_t thread_func(void *)
{
{
foo f(10);
} // Here the destructor will be called....
chThdExit(0);
}
Martin