How do you get a global var to be instantiated as the very first thing in C++ under win32?
sI'm on Windows and I'm building a C++ project with VS2008. I'm trying to replace new/delete/malloc/free etc. Which is working i.e. my replacements are getting called.
However my replacement allocator needs to be initialised. I have done this thus far by defining it as a global variable in a .cpp file with the #pragma init_seg(lib) defined inside it.
This worked up until recently when std::locale started to get initialised which was calling 开发者_运维百科new before my allocator was getting initialised. So I nervously moved my allocator's global variable to the compiler segment ie #pragma init_seg(compiler).
This worked for a bit and then I decided to override malloc. Now I get a malloc call in __crtGetStringTypeA_stat in _tmainCRTStartup which is before even the global vars in the compiler segment have been initialised.
Is there any way to get my variable be instantiated before the CRT start up. The only thing I can think of is rebuilding my crt lib and trying some how to insert my initialisation code in there some where. I presume there must be a crt clean up function as well?
Is there an easier route to this and/or something obvious I'm missing here?
You are using a static storage duration
object.
But you are having problems with the order of initialization.
To solve this use a static storage duration object that is defined within a function scope.
MyAllocator& getAllocator()
{
static MyAllocator allocator; // Note the static here.
// It has the appropriate lifespan and will be destoryed.
// and is automatically constructed the first time this
// function is called.
return allocator;
}
Now your versions of new/delete/ etc can get a reference to the allocator by calling getAllocator(). This will guarantee that the object is correctly initialized (assuming MyAllocator has the correct constructor).
On windows, you can use InitOnceExecuteOnce
to initialize your allocator. For example:
static INIT_ONCE initFlag = INIT_ONCE_STATIC_INIT;
static BOOL CALLBACK InitMyHeap(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
{
*Context = (PVOID)CreateMyHeap();
}
MyHeap *GetMyHeap()
{
PVOID vpMyHeap;
if (!InitOnceExecuteOnce(&initFlag, InitMyHeap, NULL, *vpMyHeap)) {
abort();
}
return (MyHeap *)vpMyHeap;
}
With this, your heap will be initialized exactly once, after GetMyHeap()
is called. Your new
/delete
/malloc
overrides should then call GetMyHeap()
to obtain a pointer to the heap structure (or to simply ensure the heap is initialized). This is safe even with multiple threads, and even if it occurs before CRT initialization, as initFlag
is static data in your data segment, and does not require a constructor call.
Note, of course, that CreateMyHeap()
must be careful not to make use of CRT services; directly call into Windows DLL functions (ie, kernel32.dll
and friends) only.
精彩评论