2

为了解决由静态(反)初始化命令失败引起的问题,我尝试使用Nifty Counter 成语 aka Schwartz Counter。但是,我注意到,如果包含静态初始化程序的头文件包含在 Visual Studio 的预编译头文件中,它就不起作用。在这种情况下,我在调试器中看到,静态初始化程序的构造函数在另一个静态对象的构造函数之后调用。

如果我在之后声明一个额外的静态初始化程序#include "stdafx.h"或编辑预编译的头文件以不包含声明,它会按预期工作。

有什么想法可能导致这种情况吗?

编辑


我终于能够在一个新的虚拟项目中重现这个问题:

Foo.cpp

#include "stdafx.h"
#include "Foo.h"

#include <cassert>
#include <iostream>

#ifdef NIFTY
static int SchwartzCounter; // zero initialized at load time
static typename std::aligned_storage<sizeof(Foo), alignof (Foo)>::type foo_buf;

Foo& foo = reinterpret_cast<Foo&>(foo_buf);
#else
Foo foo;
#endif

Foo::Foo()
{
    std::cout << __func__ << std::endl;
}

Foo::~Foo()
{
    std::cout << __func__ << std::endl;
}

void Foo::doSomething()
{
    std::cout << __func__ << std::endl;
    assert(x == 42);
}

#ifdef NIFTY
FooInitializer::FooInitializer()
{
    std::cout << __func__ << std::endl;

    if (SchwartzCounter++ == 0)
    {
        new (&foo) Foo();
    }
}

FooInitializer::~FooInitializer()
{
    std::cout << __func__ << std::endl;

    if (--SchwartzCounter == 0)
    {
        (&foo)->~Foo();
    }
}
#endif

Foo.h

#pragma once
class Foo
{
public:
    Foo();
    ~Foo();

    void doSomething();

private:
    int x = 42;
};

#ifdef NIFTY
extern Foo& foo;

static struct FooInitializer {
    FooInitializer();
    ~FooInitializer();
} fooInitializer;
#else
extern Foo foo;
#endif

条形图.cpp

#include "stdafx.h"
#include "Foo.h"
#include "Bar.h"

#include <cassert>
#include <iostream>

#ifdef NIFTY
static int SchwartzCounter; // zero initialized at load time
static typename std::aligned_storage<sizeof(Bar), alignof (Bar)>::type bar_buf;

Bar& bar = reinterpret_cast<Bar&>(bar_buf);
#else
Bar bar;
#endif

Bar::Bar()
{
    std::cout << __func__ << std::endl;
    foo.doSomething();
}

Bar::~Bar()
{
    std::cout << __func__ << std::endl;
}

void Bar::doSomething()
{
    std::cout << __func__ << std::endl;
    assert(x == 42);
}

#ifdef NIFTY
BarInitializer::BarInitializer()
{
    std::cout << __func__ << std::endl;

    if (SchwartzCounter++ == 0)
    {
        new (&bar) Bar();
    }
}

BarInitializer::~BarInitializer()
{
    std::cout << __func__ << std::endl;

    if (--SchwartzCounter == 0)
    {
        (&bar)->~Bar();
    }
}
#endif

酒吧.h

#pragma once
class Bar
{
public:
    Bar();
    ~Bar();

    void doSomething();

private:
    int x = 42;
};

#ifdef NIFTY
extern Bar& bar;

static struct BarInitializer {
    BarInitializer();
    ~BarInitializer();
} barInitializer;
#else
extern Bar bar;
#endif

标准数据文件

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>

// If the following define is commented out, the nifty counter idiom is not used
#define NIFTY

// If the following include is commented out while the nifty counter idiom is used, the initialization order is correct
#include "Foo.h"
4

0 回答 0