简体   繁体   English

你如何在win32下的C++中首先实例化一个全局变量?

[英]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.我在 Windows 上,我正在用 VS2008 构建一个 C++ 项目。 I'm trying to replace new/delete/malloc/free etc. Which is working ie my replacements are getting called.我正在尝试替换 new/delete/malloc/free 等。这是有效的,即我的替换被调用。

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.到目前为止,我通过将其定义为 a.cpp 文件中的全局变量并在其中定义了 #pragma init_seg(lib) 来做到这一点。

This worked up until recently when std::locale started to get initialised which was calling new before my allocator was getting initialised.直到最近,当 std::locale 开始初始化时,这一直有效,它在我的分配器初始化之前调用 new 。 So I nervously moved my allocator's global variable to the compiler segment ie #pragma init_seg(compiler).所以我紧张地将分配器的全局变量移到编译器段,即#pragma init_seg(compiler)。

This worked for a bit and then I decided to override malloc.这工作了一段时间,然后我决定覆盖 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.现在我在 _tmainCRTStartup 的 __crtGetStringTypeA_stat 中得到了一个 malloc 调用,这甚至在编译器段中的全局变量被初始化之前。

Is there any way to get my variable be instantiated before the CRT start up.有什么方法可以在 CRT 启动之前实例化我的变量。 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.我唯一能想到的就是重建我的 crt 库并尝试一些如何将我的初始化代码插入其中的某个地方。 I presume there must be a crt clean up function as well?我想也必须有一个crt清理function?

Is there an easier route to this and/or something obvious I'm missing here?有没有更简单的途径和/或我在这里遗漏的明显东西?

You are using a static storage duration object.您正在使用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.要解决此问题,请使用 static 存储持续时间 object ,它在 function Z31A1FD140BE4BEF2D181E18A12 中定义

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().现在,您的 new/delete/ 等版本可以通过调用 getAllocator() 来获取对分配器的引用。 This will guarantee that the object is correctly initialized (assuming MyAllocator has the correct constructor).这将保证 object 被正确初始化(假设 MyAllocator 具有正确的构造函数)。

On windows, you can use InitOnceExecuteOnce to initialize your allocator.在 windows 上,您可以使用InitOnceExecuteOnce来初始化分配器。 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.这样,在GetMyHeap()之后,您的堆将被初始化一次。 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).然后,您的new / delete / malloc覆盖应调用GetMyHeap()以获取指向堆结构的指针(或简单地确保堆已初始化)。 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.即使使用多个线程也是安全的,即使它发生在 CRT 初始化之前,因为initFlag是数据段中的 static 数据,并且不需要构造函数调用。

Note, of course, that CreateMyHeap() must be careful not to make use of CRT services;当然,请注意CreateMyHeap()必须注意不要使用 CRT 服务; directly call into Windows DLL functions (ie, kernel32.dll and friends) only.仅直接调用 Windows DLL 函数(即kernel32.dll和朋友)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM