Compiler question: doesn't call global instance constructor

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Compiler question: doesn't call global instance constructor

Jump to solution
2,070 Views
eGuy
Contributor IV

Hi,

 

I am using  Codewarrior development studi for ColdFire V7.1

 

The test code I have like below:

 

-------------------------------------------------------------

class testGroupStackTest
{ public:
    

     testGroupStackTest ()     {    dummy =123;   }
   
     int getdummy()    {    return dummy;  }
   
     int dummy;
 };

testGroupStackTest testGroupStackInstance;

/* Task IDs */
#define HELLO_TASK 5

extern void hello_task(uint_32);

extern "C" const TASK_TEMPLATE_STRUCT  MQX_template_list[] =
{
   /* Task Index,   Function,   Stack,  Priority, Name,     Attributes,          Param, Time Slice */
    { HELLO_TASK,   hello_task, 1500,   5,        "hello",  MQX_AUTO_START_TASK, 0,     0 },
    { 0 }
};


void hello_task
   (
      uint_32 initial_data
   )
{
int i;
//testGroupStackTest testGroupStackInstance;

   printf("\n Hello World \n");
 
   i=testGroupStackInstance.getdummy();
   printf("dummy=%d\n",i);

   printf("\n Tests Done \n");

  _mqx_exit(0);

}
------------------------------------------------------

 

if I define testGroupStackInstance as Global instance, the constructor is never got called, the i value I get is Zero. however if I define testGroupStackInstance inside the task, I can get the correct i value dummy =123. What I am missing here?

 

Your help is great appreciated.

 

Thanks.

 

J.

Labels (1)
1 Solution
661 Views
eGuy
Contributor IV
Problem found:

 

MQX overrides C++ initialization code in cw.c, see below:

 

-------------------------------------------------------------------------

cw.c

 

/* Override C++ inititialization so it happens later in _bsp_enable_card */
void __call_static_initializers(void){}
#pragma overload void __call_static_initializers(void);
------------------------------------------------------------------------

 

We need to enable  BSPCFG_ENABLE_CPP in the configuration, so later the in _bsp_enable_card(), MQX will do the C++ constructor initialization, see below:

 

---------------------------------------------------------

init_bsp.c     _bsp_enable_card

 

#if BSPCFG_ENABLE_CPP
   /* initialize C++ constructors */
   __cpp_init();
#endif
 --------------------------------------------------------

 

Happy Thanksgivings

 

J.

View solution in original post

5 Replies
662 Views
eGuy
Contributor IV
Problem found:

 

MQX overrides C++ initialization code in cw.c, see below:

 

-------------------------------------------------------------------------

cw.c

 

/* Override C++ inititialization so it happens later in _bsp_enable_card */
void __call_static_initializers(void){}
#pragma overload void __call_static_initializers(void);
------------------------------------------------------------------------

 

We need to enable  BSPCFG_ENABLE_CPP in the configuration, so later the in _bsp_enable_card(), MQX will do the C++ constructor initialization, see below:

 

---------------------------------------------------------

init_bsp.c     _bsp_enable_card

 

#if BSPCFG_ENABLE_CPP
   /* initialize C++ constructors */
   __cpp_init();
#endif
 --------------------------------------------------------

 

Happy Thanksgivings

 

J.

661 Views
same
Contributor II

Hi eGuy

I want to use Cppunit in CodeWarrior too, but I couldn't add it to my project.

In fact I added it to path and CodeWarrior can find header files, but for building the project I am getting so many error messages like:

=#include <string>

>the file 'string' cannot be opened

OR

(C:\cppunit\include\cppunit\TestCase.h|32|20|3|706|3)

=    TestCase( const std::string &name );

>declaration syntax error

Can I ask you how did you use CppUnit in your project?

Regards

0 Kudos
661 Views
CrasyCat
Specialist III

Hello

 

When you did create your project from a stationery, did you specify you want to use C++?

 

When you are using global classes, you need a startup code, where the function __call_static_initializers is called. Additionally you need to make sure you link against Cpp run time library (Cpp_4i_CF_Runtime.a for example).

 

All these settings are set up appropriately if you let the project wizard know you intend to use C++ source file in your application.

 

CrasyCat

0 Kudos
661 Views
eGuy
Contributor IV

Hi Lundin & CrasyCat,

 

Thank both of you for your quick response.

 

I didn't created the project from scatch/stationery. I modified some example code ( in C ) from MQX's example. I added CPP_4i_CF_RegABI_Runtime.a and C++_4i_CF_RegABI_MSL.a manually to the project.

 

Is there any way that I can specify I want to use C++ in the project setting page? (I tried "Force C++ compilation on C/C++ language page, it doesn't work)

 

I will try to start project from a stationery  later today.

 

Lundin, I am trying to use CppUnitLite in my project, that CppUnit registration machnism macros require global object instantiation.

 

Thanks again.

 

0 Kudos
661 Views
Lundin
Senior Contributor IV
The most likely cause is that you choosed to have a quick, non ISO-compliant startup code when you created the project.

At project creation you can choose to use static initialization or not. Static initialization means that all statically allocated variables (static, globals etc) are initialized at startup, as required by ISO C / ISO C++. It also means that C++ constructors for statically allocated C++ objects will have their constructors called.

In embedded systems, you typically want to avoid static initalization and init every variable in runtime instead, and call constructors in runtime instead. The C/C++ standards were designed for RAM-based desktop/telecom applications where the code doesn't sit in NVM at startup. Therefore C/C++ has requirements such as "all static variables must be zero before the program is started". In a NVM system such requirements are burdensome, as they mean you must run a lot of "copy-down" procedures before the system is started.

To avoid this copy-down mess in embedded systems, you write the programs in such a way that they don't rely on static initialization. Ie instead of writing:

int x = 5;

you write

int x;

...
void init_function()
{
x = 5;
}

The very same applies to C++ constructors, you should call them in runtime and not at startup time.
Message Edited by Lundin on 2009-11-24 04:16 PM
0 Kudos