How to call global constructors

From SEGGER Wiki
Jump to: navigation, search

Global objects of C++ classes need to be constructed by the runtime initialization. With the SEGGER Linker this can be done automatically.

In case a constructor makes use of system operations, such as it uses RTOS functions, initialization needs to be deferred until the system is setup.

Automatic Initialization

With a global class object, such as the following, the constructor for the instance is linked into the section .ctors or into init_array.

class foo {
public:
  foo(void) {
    printf("Foo initialized.\n");
  }
};

static foo MyFoo;

The linker script defines a block for all constructors and automatically does the initialization when there is at least one constructor to call.

  define block ctors                          { section .ctors,     section .ctors.*, block with         alphabetical order { init_array } };
  define block dtors                          { section .dtors,     section .dtors.*, block with reverse alphabetical order { fini_array } };

  initialize by calling __SEGGER_init_ctors   { block ctors }; // Call constructors for global objects which need to be constructed before reaching main (if any). Make sure this is done after setting up heap.

Manual Initialization

It is usually a problem when a constructor uses RTOS functions and is called before main(). In that case the initialization should be done after the basic system is set up.

Remove initialize by calling __SEGGER_init_ctors from the linker script and add the following function:

extern void (*__ctors_start__[])(void);
extern void (*__ctors_end__[])(void);

void init_ctors(void);
void init_ctors(void) {
  void (**f)(void);
 
  for (f = __ctors_start__; f < __ctors_end__; f++) {
    (*f)(); 
  }
}

Call init_ctors in the application:

int main(void) {
  OS_Init()     // Initialize RTOS
  init_ctors(); // Late initialization of constructors
  OS_Start();   // Start RTOS
}