PDA

View Full Version : C++ constructors for static objects in functions don't seem to be called.



froeber
10-28-2013, 01:30 PM
I had some code that was working just fine measuring elapsed time using C++ elapsedMillis objects that were defined as static objects at file level scope (ie outside any functions). To improve maintainability I moved some of the static elapsed time objects into the functions they were associated with. And they no longer worked -- meaning they didn't measure elapsed time right. I'm suspecting that it's an issue with the constructor table that the tool chain builds. "Normally" when doing host based development the calling of constructors and destructors for C++ is handled automatically. I understand that it's trickier with embedded code. I think the constructors are not being called for objects inside functions.

My "solution" is to just not use C++ static objects inside functions. Just wanted to warn other people about this issue. I looked and couldn't find another post about this problem. I doubt it's platform-specific but I'm developing on Windows using the recent 1.16 release with Arduino 1.0.5.

Koromix
12-15-2013, 05:24 PM
First, I want to apologize for my poor English and thank you for the great product that is the Teensy.

I've got (almost) the same problem here on my Teensy 3.0, which can be fixed by moving the static declarations outside of functions. Problem is, it leads to name clashes and prohibits the use of macros that need to declare static objects. Obviously, integer variables are not reset, the problem being that constructors are called each time.

Here is an example using a class of mine, Delay, which is like Metro from your libraries but with more options. This example should led to the integrated LED being switched every 500 ms. it works if you move the static Delay declaration outside of loop(), but fails otherwise.

stevech
12-15-2013, 07:25 PM
Initializizers for C++ static objects... I think its up to the compiler to generate this code. And some don't. That code has to be called by the hardware initialization code runs - and I've seen that be the problem. Compiler doesn't know what that code is.

Koromix
12-15-2013, 07:35 PM
Actually, function scoped class constructors are supposed to be called the first time a function is called. This relies on __cxa_guard_* functions which are not correctly implemented for Teensy 3.x. Here is a simple patch that fixes mk20dx128.c. Fixes the bug for me.


--- a/hardware/teensy/cores/teensy3/mk20dx128.c 2013-12-15 21:21:04.668708500 +0100
+++ b/hardware/teensy/cores/teensy3/mk20dx128.c 2013-12-15 21:26:35.634256734 +0100
@@ -538,12 +538,13 @@
__attribute__((weak))
int __cxa_guard_acquire (int *g)
{
- return 1;
+ return !(*g);
}

__attribute__((weak))
void __cxa_guard_release(int *g)
{
+ *g = 1;
}

int nvic_execution_priority(void)

Of course, this is not thread-safe as is the code for previous Teensy iterations.