如何在win32下将全局变量实例化为c++中的第一件事?

How do you get a global var to be instantiated as the very first thing in C++ under win32?

本文关键字:一件 c++ win32 实例化 全局变量      更新时间:2023-10-16

我在Windows上,我正在用VS2008构建一个c++项目。我试图取代新的/删除/malloc/自由等。这是有效的,也就是说,我的替代者正在被召唤。

但是我的替换分配器需要初始化。到目前为止,我已经将它定义为.cpp文件中的全局变量,其中定义了#pragma init_seg(lib)。

这个问题直到最近std::locale开始被初始化,在我的分配器被初始化之前调用new。因此,我紧张地将分配器的全局变量移动到编译器段,即#pragma init_seg(编译器)。

这工作了一点,然后我决定覆盖malloc。现在我在_tmainCRTStartup中的__crtGetStringTypeA_stat中得到一个malloc调用,这甚至是在编译器段中的全局变量被初始化之前。

有没有办法让我的变量在CRT启动之前实例化。我唯一能想到的是重建我的crt库,并尝试一些如何插入我的初始化代码在那里的一些地方。我想应该还有一个crt清理功能吧?

是否有更容易的途径和/或我在这里错过的一些明显的东西?

您正在使用static storage duration对象。

但是你的初始化顺序有问题。
要解决这个问题,可以使用在函数作用域中定义的静态存储持续时间对象。

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;
}

现在你的new/delete/etc版本可以通过调用getAllocator()来获取对分配器的引用。这将保证对象被正确初始化(假设MyAllocator具有正确的构造函数)。

在windows上,您可以使用InitOnceExecuteOnce初始化您的分配器。例如:

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;
}

这样,在调用GetMyHeap()之后,堆将只初始化一次。然后,您的new/delete/malloc重写应该调用GetMyHeap()来获取指向堆结构的指针(或者只是确保堆被初始化)。这是安全的,即使在多线程中,即使它发生在CRT初始化之前,因为initFlag是数据段中的静态数据,不需要调用构造函数。

当然,CreateMyHeap()必须小心不要使用CRT服务;直接调用到Windows DLL函数(即kernel32.dll和朋友)。