我在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
个对象之前被初始化?
答案 0 :(得分:13)
其中一个解决方案是尝试将静态变量包装到静态函数中:
static type& My_static_obj() {
static type my_static_obj_;
return my_static_obj_;
}
它看起来像一个简单类型的Singleton并调用 Construct On First Use Idiom 。由于标准(C ++ 11及以上版本),它保证初始化一次(甚至原子化!),并且在其c-tor内部,这样的对象可以访问其他"静态"变量,因此,如果变量之间没有循环依赖关系,则将严格定义初始化顺序。
有关其他信息,请参阅this question以及此首次使用成语构建的其他说明。
答案 1 :(得分:3)
在这种情况下,nifty counter成语可能会以某种方式帮助你:
确保在首次使用之前初始化非本地静态对象,并且仅在最后一次使用该对象后将其销毁。
它的动机很明确:
当静态对象使用其他静态对象时,初始化问题变得更加复杂。如果静态对象具有非平凡的初始化,则必须在使用之前对其进行初始化。编译单元中静态对象的初始化顺序没有明确定义。跨多个编译单元的多个静态对象可能使用单个静态对象。因此,必须在使用前进行初始化。一个例子是std :: cout,它通常被许多其他静态对象使用。
直接复制并粘贴上述链接页面中的示例是值得的:
<强> Stream.h 强>
library(purrr)
states <- state.abb[1:27]
agencies <- c("AID", "AMBC", "AMTRAK", "APHIS", "ATF", "BBG", "DOJ", "DOT",
"BIA", "BLM", "BOP", "CBFO", "CBP", "CCR", "CEQ", "CFTC", "CIA",
"CIS", "CMS", "CNS", "CO", "CPSC", "CRIM", "CRT", "CSB", "CSOSA",
"DA", "DEA", "DHS", "DIA", "DNFSB", "DOC", "DOD", "DOE", "DOI")
walk(states, function(x) {
map(x, ~sprintf("http://website.gov/%s_%s.zip", ., agencies)) %>%
flatten_chr() -> urls
download.file(urls, basename(urls), method="libcurl")
})
<强> Stream.cpp 强>
#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类的头文件,然后才能在Stream对象上调用任何成员函数。每个编译单元中都包含StreamInitializer类的实例。任何对Stream对象的使用都遵循包含标头,这确保在使用Stream对象之前调用初始化对象的构造函数。
有关详细信息,请参阅上面的链接。
答案 2 :(得分:1)
我从未使用过未包含在开发环境中的STL实现,但它是可能的。将include和库路径设置为备用STL实现应该是一件简单的事情。您可以从尝试STLPort
开始否则,在上次编辑之前,我对您的问题的原始建议是:
编译单元(cpp文件)中的静态初始化顺序是声明的顺序。编译单元之间的静态初始化顺序未定义。不要使用静态初始化来解决这个问题。
看起来RustyX指向正确的方向,他的评论链接到Overriding memory allocator in MSVC++。
编辑:看起来您正在寻找的答案可能就在这里:How to properly replace global new & delete operators。请注意,这两个答案都是相关的,您需要替换new
,delete
,new[]
和delete[]
。由于这是在链接期间应用的,显然Windows不会将这些用于您加载的DLL(请参阅第一个答案的注释)。
答案 3 :(得分:0)
您可以从Chromium项目Docs获得想法。请参阅“Singleton&amp; base :: LazyInstance”部分。