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.