4

I'm trying to implement a static initializer, and in order to have it executed early I'm wrapping it as a static struct as discussed here.

char * some_global_var;

struct Init
{
    __declspec(noinline) Init() {
        some_global_var = "some_value";
    }
};

int main() {
    static Init init;
    // do stuff
    return 0;
}

... expecting the static initializer to be executed by _initterm before main() starts.

However, the code that's generated is far from that (MSVC 2015):

int main() {
000000013FCC1030  sub         rsp,28h  
    static Init init;
000000013FCC1034  mov         rax,qword ptr gs:[58h]  
000000013FCC103D  mov         edx,4  
000000013FCC1042  mov         rcx,qword ptr [rax]  
000000013FCC1045  mov         eax,dword ptr [rdx+rcx]  
000000013FCC1048  cmp         dword ptr [some_global_var+8h (013FCC4680h)],eax  
000000013FCC104E  jle         main+46h (013FCC1076h)  
000000013FCC1050  lea         rcx,[some_global_var+8h (013FCC4680h)]  
000000013FCC1057  call        _Init_thread_header (013FCC125Ch)  
000000013FCC105C  cmp         dword ptr [some_global_var+8h (013FCC4680h)],0FFFFFFFFh  
000000013FCC1063  jne         main+46h (013FCC1076h)  
000000013FCC1065  call        Init::Init (013FCC1000h)  
000000013FCC106A  lea         rcx,[some_global_var+8h (013FCC4680h)]  
000000013FCC1071  call        _Init_thread_footer (013FCC11FCh)  
    // do stuff
    return 0;
000000013FCC1076  xor         eax,eax  
}
000000013FCC1078  add         rsp,28h  
000000013FCC107C  ret  

In other words, the static initializer is executed in the scope of the function by using some (thread-local??) flag. Of course if I wanted to use a flag I would have done that myself.

So my question is - how can I achieve static initialization to happen outside main()?

Note this is a simplified situation. In the real situation I need to ensure the init code is executed before a certain function (_malloc_base, to be precise). If I just move Init to the global scope, then the constructor executed too late (if at all - in most cases it is optimized away in Release mode). Other CRT code already calls _malloc_base before my initializer is fired.

Community
  • 1
  • 1
rustyx
  • 80,671
  • 25
  • 200
  • 267

1 Answers1

2

Move the declaration of init out of main and into the global scope.

static Init init;
Int main() {
    // do stuff
    return 0;
}
Buddy
  • 10,874
  • 5
  • 41
  • 58
  • But this is a simplified situation. In the real situation I need to ensure the init code is executed before a certain function (_malloc_base, to be precise). If I just do this, then it's executed too late; other CRT code already calls _malloc_base before my initializer is fired. – rustyx Feb 20 '16 at 15:45
  • 1
    @rustyx If this is a requirement then please update your question. As it is currently written, Buddy solved it. – Martin Zabel Feb 20 '16 at 15:48
  • Because this code doesn't actually do anything. Try printing `some_global_var` from `main` and it should not get optimized away. – Buddy Feb 20 '16 at 16:43