static const array gets initialized dynamically in MSVC? static const array gets initialized dynamically in MSVC? arrays arrays

static const array gets initialized dynamically in MSVC?


  ??__EActs@@YAXXZ PROC     ; `dynamic initializer for 'Acts'', COMDAT

I'll assume that's the one you are complaining about. The single-pass compilation model is the larger obstacle here, the compiler cannot make any assumptions about the inheritance model for the parser_t class, it only has the forward declaration to work with. Member function pointers look different depending on whether the class uses single, multiple or virtual inheritance.

You need to help and tell the compiler with the appropriate non-standard extension keyword. Fix:

 class __single_inheritance parser_t;

And the table generation now changes to:

?Acts@@3QBQ8parser_t@@AGHXZB DD FLAT:?aArrayStart@parser_t@@QAGHXZ ; Acts    DD  FLAT:?aComplexEnd@parser_t@@QAGHXZ    DD  FLAT:?aObjectStart@parser_t@@QAGHXZ    etc...CONST   ENDS

And no dynamic initializer anymore.


I'm not sure why function pointer address cannot be extracted as a constant - this needs to be asked from Microsoft developers, however - I was able to walk around this problem - if you introduce some virtual function in base class - it then be able to figure out function pointer addresses correctly.

This code does not compile:

#include <stdio.h>          // printfclass CBase{public:    void func1()    {    }};class Test: public CBase{public:    virtual void func2()    {    }    void DoTest1( char* s )    {        printf("DoTest1: %s\r\n", s);    }    void DoTest2( char* s )    {        printf( "DoTest1: %s\r\n", s );    }};typedef void (Test::*funcaction) ( char* s );static constexpr funcaction g_funs[] ={    &Test::DoTest1,    &Test::DoTest2,};

This code compiles fine:

#include <stdio.h>          // printfclass CBase{public:    virtual void func1()    {    }};class Test: public CBase{public:    virtual void func2()    {    }    void DoTest1( char* s )    {        printf("DoTest1: %s\r\n", s);    }    void DoTest2( char* s )    {        printf( "DoTest1: %s\r\n", s );    }};typedef void (Test::*funcaction) ( char* s );static constexpr funcaction g_funs[] ={    &Test::DoTest1,    &Test::DoTest2,};

What's the difference - no clue. :-)


The issue is that the functions in parser_t are not static, so the compiler does not know what memory address to assign to the elements of Acts[]. If you make the functions static and provide definitions for them, then the compiler can make the associations and set the pointers to the right values. You will probably also need to alter the typedef for action_t (or make a copy).

typedef error_t (idaapi *action_t)(void);class parser_t: public basic_parser_t {public:/*  0 */ static error_t idaapi aArrayStart(void) { /*...*/ }/*...*/};static const action_t Acts[] ={/*  0 */ &parser_t::aArrayStart,/*...*/};

If you want the functions to remain non-static (e.g. parser_t is an abstract class or its functions must be non-static for other reasons), then Acts[] cannot be statically defined and you'll need to instantiate parser_t (or its fully-defined child class) and then assign the elements of Acts[] to the functions via that object.

class parser_t: public basic_parser_t {public:/*  0 */ error_t idaapi aArrayStart(void) { /* defined here or in child class */ }/*...*/};parser_t parser = new parser_t();const action_t Acts[] ={/*  0 */ &parser::aArrayStart,/*...*/};

INFO: Creating a Function Pointer to a C++ Member Function
Pointer declaration: Pointers to member functions