[Answered]: Calling functions in C++ class constructors that have static instances

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

[Answered]: Calling functions in C++ class constructors that have static instances

Postby kolban » Sun Nov 05, 2017 5:30 am

I'm chasing down some strange problems and a thought struck me that I'd like to run past the community. It relates to C++ classes and static / global class instances.

Let us imagine the following class:

Code: Select all

class MyClass {
public:
   MyClass() {
      m_semaphore = xSemaphoreCreate();
      ...
   }
   SemaphoreHandle_t m_semaphore;
}

MyClass myGlobalInstance;

main() {
 ....
}
If we study this code, we will find that its constructor creates an instance of a semaphore that is presumably used elsewhere in the class. Now also notice that there is a global instance of the class created and made available in the variable called myGlobalInstance.

Let us think about that for a second. Since it is a C++ class instance, that means that its constructor was called. Since its constructor was called, that means that the code defined in the constructor was called. And now comes the key question ... what ESP-IDF/FreeRTOS calls are legitimate within this context?

If the instance weren't defined as global but was instead created in the context of a function ... for example:

Code: Select all

main() {
 MyClass myLocalInstance;
}
I think any and all code/logic would be fair game. However, in a global variable, the code is executed before control is given to main (or app_main() in ESP32). But is this too early? What (if anything) can we claim about the context/state/environment in which constructors defined in global class instances execute within? For example, do they execute before "enough" of ESP-IDF/FreeRTOS is initialized?
Last edited by kolban on Mon Nov 20, 2017 3:23 am, edited 1 time in total.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

fermienrico
Posts: 11
Joined: Sat Oct 14, 2017 6:31 am

Re: Calling functions in C++ class constructors that have static instances

Postby fermienrico » Sun Nov 05, 2017 5:36 am

You might enjoy this: https://isocpp.org/wiki/faq/ctors#static-init-order

:lol:

In principle, a variable defined outside any function (that is, global, namespace, and class static variables) is initialized before main() is invoked. Such nonlocal variables in a translation unit are initialized in their declaration order (§10.4.9). If such a variable has no explicit initializer, it is by default initialized to the default for its type (§10.4.2). The default initializer value for built-in types and enumerations is 0. [...] There is no guaranteed order of initialization of global variables in different translation units. Consequently, it is unwise to create order dependencies between initializers of global variables in different compilation units. In addition, it is not possible to catch an exception thrown by the initializer of a global variable (§14.7). It is generally best to minimize the use of global variables and in particular to limit the use of global variables requiring complicated initialization. - Bjarne Stroutrup
It is compiler dependent and need someone from the ESP/xtensa /GCC compiler team to shed some light on this.

ESP_Sprite
Posts: 9766
Joined: Thu Nov 26, 2015 4:08 am

Re: Calling functions in C++ class constructors that have static instances

Postby ESP_Sprite » Sun Nov 19, 2017 3:52 pm

The global constructors are called in components/esp32/cpu_start.c, function do_global_ctors, called from start_cpu0_default. Specifically, this is done outside of a thread context, and with the FreeRTOS scheduler not running yet; this means that you can create semaphores, queues, threads etc, but that they will not be functional until the scheduler has been started.

BuddyCasino
Posts: 263
Joined: Sun Jun 19, 2016 12:00 am

Re: [Answered]: Calling functions in C++ class constructors that have static instances

Postby BuddyCasino » Mon Nov 20, 2017 10:26 am

And thus the C++ learning curve strikes again:

Image

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: [Answered]: Calling functions in C++ class constructors that have static instances

Postby kolban » Mon Nov 20, 2017 1:58 pm

I'm a self professed C++ fan boy (compared to C). I do like the diagram and each of the features of the C++ language listed there I most certainly agree with require study and understanding. There is no question that C++ is a rich and complex language. A C++ program can fail in new and interesting ways compared to a C program. My only rebuttal would be that a C++ programmer doesn't have to use all the features of the language if they are not comfortable with them. For example, Ive never needed to code a C++ template in my life. However, should a puzzle present itself in the future that just screams "I wish I had templating" ... I know enough to know its there and can go hit the books.

The puzzle presented in this post wasn't a failing or strangeness in the C++ language ... rather it was a query on the relationship of C++ within (specifically) the ESP32 environment as it relates to FreeRTOS.

Interestingly, the same question applies in C programming if one uses the "constructor" attribute. For example, in C:

Code: Select all

__attribute__((constructor)) static void myfunc() {
   /// your code here
};
would have the same puzzle.

https://stackoverflow.com/questions/205 ... uctor-work
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

Who is online

Users browsing this forum: No registered users and 67 guests