函数内的C ++多线程静态POD初始化

时间:2017-05-10 06:25:48

标签: c++ multithreading visual-c++ static

如果静态POD是多个线程调用的函数中的静态变量,我不确定静态POD是否实际上可以多次初始化为零:

void CalledByManyThreads()
{
    struct StaticClass
    {
        struct POD { volatile LONG value; } pod; // Using MSVC specific volatile behaviour - I don't care about std::atomic


        StaticClass()   //  Constructor makes the struct a non-POD so we likely need the extra POD struct for our member data
        {
            while (pod.value == 0)
                if (InterlockedCompareExchange(&pod.value, 0, 1) == 0)
                {
                    //  Is it possible that another thread zero initialises pod after we have just set it to 1?
                    break;
                }
        }
    };


    static StaticClass test;    //  When is test.pod zero initialised in MSVC 2013+?
}

围绕这个功能领域,强制性C ++标准与编译器的实际行为之间存在差异 - 我对MSVC2013以后的现有编译器的实际情况更感兴趣。

是否有可能一个线程将pod.value设置为1但是在另一个竞争线程零之后将其初始化为0?

1 个答案:

答案 0 :(得分:1)

MSVC 2013不支持“魔法静态”MSDN : C++11 support。我还在较早时间验证了生成的代码,并确认它不支持它们。

VS2015似乎确实正常工作(并标记为这样)。

VS2013中生成的代码与早期代码相同,后者具有线程不安全机制,用于检测变量是否已构造。这是必要的。此测试+构建对象的时间是比赛发生的时间长度。

完成一个项目后,没有进一步的重建。

我在VS2013中发现了许多编译器问题(例如,在运行时在VM中运行时错误检测运行时库中的AVX命令),Microsoft已建议任何已识别的问题升级编译器。 Microsoft connect : AVX generates illegal instruction

这是我对你的推荐。

  

是否有可能一个线程将pod.value设置为1但是在另一个竞争线程零之后将其初始化为0?

编译器有3个计划来初始化程序中的静态数据。

  • 非常静态数据
  • 静态数据
  • 非pod数据。

非常静态数据

当编译器看到一个可以在编译时完全知道的数据结构时,它将为obj文件中的结构创建内存,该文件将具有最终文件的正确布局。这不会多次初始化。

静态数据

如果使用在编译时未完全知道的信息初始化POD结构,则将创建未知元素的构造函数。在我确定的情况下

struct memoryAllocator {
     void * (*mallocFunction)( size_t size );
     int initialized;
}

memoryAllocator alloc { malloc, 1 };

alloc初始化为初始化设置为1作为静态数据,然后在main之前用导入的malloc的值构造。似乎没有C ++要求构造对象是全有或全无。这似乎是对我的疏忽。

非pod数据

这被初始化为构造函数。在静态函数中,代码由变量保护,该变量描述初始化是否已完成。

从查看代码开始,

  1. 未初始化POD结构中的数据
  2. 未编写value能够从1过渡到0的代码。
  3. 在这个术语中,我希望POD数据保持未初始化和0(因为它是静态的),并且构造函数是唯一要调用的项目,并且将数据修改为1(由于互锁)。