我可以在C 中更改静态变量初始化顺序吗?
Can I change static variable initialization order in C++?
i在Visual Studio 2015 SP3中使用C 。
#pragma init_seg(compiler)
,我首先初始化一些静态变量(用于内存管理)。https://msdn.microsoft.com/en-us/library/7977wcck.aspx
但是,有
#pragma init_seg(compiler)
在wcerr.cpp(Microsoft Visual Studio 14.0 vc crt src stl wcerr.cpp)中,因此这些对象是在我的对象之前初始初始化的。
我可以通过任何编译/链接选项在wcerr.cpp
对象之前先初始化我的对象?
解决方案之一是尝试将静态变量包装到静态函数:
static type& My_static_obj() {
static type my_static_obj_;
return my_static_obj_;
}
它看起来像一种简单的单顿类型,并在首次使用idiom 上调用。由于标准(C 11及以上),它可以保证一次初始化一次(甚至是原子!),并且在其C-tor内部,这样的对象可以访问其他"静态"变量,因此,如果没有圆形变量之间的依赖项,初始化的顺序将被严格定义。
有关其他信息,请参见此问题和此首先使用Idiom 的其他描述。
可能在这种情况下以某种方式可以帮助您:
确保非本地静态对象在首次使用之前初始化并仅在上次使用对象后被销毁。
它的动机非常明显:
当静态对象使用其他静态对象时,初始化问题变得更加复杂。如果静态对象具有非平凡的初始化,则必须在使用之前初始化其使用。跨编译单元的静态对象的初始化顺序没有明确定义。多个静态对象,分布在多个汇编单元上,可能使用一个静态对象。因此,必须在使用前初始化它。一个示例是std :: cout,通常由许多其他静态对象使用。
值得从上面的链接页面中直接复制并粘贴示例:
stream.h
#ifndef STREAM_H
#define STREAM_H
struct Stream {
Stream ();
~Stream ();
};
extern Stream& stream; // global stream object
static struct StreamInitializer {
StreamInitializer ();
~StreamInitializer ();
} streamInitializer; // static initializer for every translation unit
#endif // STREAM_H
stream.cpp
#include "Stream.h"
#include <new> // placement new
#include <type_traits> // aligned_storage
static int nifty_counter; // zero initialized at load time
static typename std::aligned_storage<sizeof (Stream), alignof (Stream)>::type
stream_buf; // memory for the stream object
Stream& stream = reinterpret_cast<Stream&> (stream_buf);
Stream::Stream ()
{
// initialize things
}
Stream::~Stream ()
{
// clean-up
}
StreamInitializer::StreamInitializer ()
{
if (nifty_counter++ == 0) new (&stream) Stream (); // placement new
}
StreamInitializer::~StreamInitializer ()
{
if (--nifty_counter == 0) (&stream)->~Stream ();
}
在流对象上调用任何成员函数之前,必须包括流类的标头文件。每个汇编单元中都包含了流媒体化合物类的实例。流对象的任何使用都遵循标头的包含,该对象确保在使用流对象之前调用初始化器对象的构造函数。
有关更多详细信息,请参见上面的链接。
编辑:我认为您需要的解决方案是使用另一个STL实现,如果您需要使用MSVC 2015并避免重新实现当前的内存管理黑客攻击(对不起,请称呼它,但这就是听起来像是什么,但是我又使用了一些自己的黑客来使用MSVC)。
我从未使用过开发环境中未包含的STL实现,但这是可能的。设置替代STL实现的包含路径和库路径应该是一个简单的问题。您可能会从尝试Stlport
开始否则,我对您的问题的最初建议是在上次编辑之前:
汇编单元(CPP文件)中的静态初始化顺序是发表声明的顺序。编译单元之间的静态初始化顺序是未定义的。请勿使用静态初始化来解决此问题。
看起来Rustyx将您指向正确的方向,他的评论链接到MSVC 中的覆盖记忆分配器。
编辑:看来您正在寻找的答案可能在这里:如何正确替换全局新&amp;删除操作员。请注意,这两个答案都是相关的,您将需要替换new
,delete
,new[]
和delete[]
。由于这是在链接过程中应用的,因此显然Windows不会将其用于您加载的DLL(请参阅第一个答案的评论)。
- 初始值设定项列表是否只接受使用相同类型的值初始化变量?
- 在 C++ 中访问 lambda 捕获初始化变量
- 为什么C++不支持对未初始化变量进行智能分析?
- 使用 clang++ 和 g++ 在C++中初始化变量
- C++使用 lambda 初始化变量
- 如何在初始化列表中的构造函数之后初始化变量/对象?
- C++ - 输出与初始化变量不同?
- C++/Win32 构造函数不使用从对话框获取的字符串初始化变量
- 在C++中,为什么int可以使用new运算符初始化变量,而double不能
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- C++ 中的初始化变量
- C++中未初始化变量的值
- 如何在需要提及需要循环声明的其他类的类中初始化变量?
- 我想知道在构造函数中初始化变量时的生命周期
- 读取恰好具有良好值的未初始化变量
- 如何在 getter 的父类中初始化变量的情况下访问子类中的变量
- 为什么在 c++ 中有多种初始化变量的方法
- 没有参数的默认构造函数是否总是初始化变量?
- 是否可以使用 lambda 初始化变量(删除复制 ctor 时)
- 使用构造函数跳闸UB的新放置后使用初始化变量