静态const数组在MSVC中动态初始化?

Igo*_*sky 12 c++ arrays visual-c++ static-initialization

我们有一个表我们想要静态初始化,但MSVC(2015.1及更早版本)也会生成动态初始化程序.

以下是演示此问题的简化代码:

#define idaapi __stdcall
#define MAXSTR 1024
typedef int error_t;
typedef unsigned char uchar;


struct psymbol_t
{
  short what;           /* -1 - is error,                       */
                        /* 0 - any symbol,don't skip it         */
                        /* else lxtype_t                        */
  short callNumber;     /* Number in table of metasymbols       */
                        /* -1 - no metasymbol                   */
                        /* Error code if what == -1             */
  uchar  nextNumber;    /* Number in current table              */
                        /* 0xFF - end                           */
  uchar  actNumber;     /* Number in Actions table              */
                        /* 0xFF - no action                     */
};

class parser_t;
typedef error_t (idaapi parser_t::*action_t)(void);
typedef error_t (idaapi parser_t::*nexttoken_t)(void);

struct token_t
{
  int type;          ///< see \ref lx_
  char str[MAXSTR];     ///< idents & strings
};

class basic_parser_t
{
  nexttoken_t gettok;
  const psymbol_t *const *Table;
  const action_t *Actions;
  bool got_token;
public:
  token_t ahead;
  //bool exported_parse(int goal) { return basic_parser_parse(this, goal); }
};


class parser_t: public basic_parser_t {
public:
/*  0 */ error_t idaapi aArrayStart(void);
/*  1 */ error_t idaapi aComplexEnd(void);
/*  2 */ error_t idaapi aObjectStart(void);
/*  3 */ error_t idaapi aObjectKvpNew(void);
/*  4 */ error_t idaapi aObjectKvpKey(void);
/*  5 */ error_t idaapi aConstant(void);
};


static const action_t Acts[] =
{
/*  0 */ &parser_t::aArrayStart,
/*  1 */ &parser_t::aComplexEnd,
/*  2 */ &parser_t::aObjectStart,
/*  3 */ &parser_t::aObjectKvpNew,
/*  4 */ &parser_t::aObjectKvpKey,
/*  5 */ &parser_t::aConstant
};
Run Code Online (Sandbox Code Playgroud)

编译与在.asm文件中/FAs /c生成一个dynamic initializer for 'Acts'函数而不是一个漂亮的常量数组.

更换最后const通过constexpr产生这样的警告:

t.cpp(54):错误C2131:表达式没有计算到常量
t.cpp(54):注意:遇到非常量(子)表达式

但是我没有看到这里的非常数.任何提示?

Han*_*ant 8

  ??__EActs@@YAXXZ PROC     ; `dynamic initializer for 'Acts'', COMDAT
Run Code Online (Sandbox Code Playgroud)

我会假设那是你抱怨的那个.单通道编译模型在这里是一个较大的障碍,编译器不能对parser_t类的继承模型做任何假设,它只有前向声明才能使用.成员函数指针看起来不同,具体取决于类是使用单继承,多继承还是虚拟继承.

您需要帮助并使用适当的非标准扩展关键字告诉编译器.固定:

 class __single_inheritance parser_t;
Run Code Online (Sandbox Code Playgroud)

表生成现在变为:

?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
Run Code Online (Sandbox Code Playgroud)

而且没有动态初始化器.