有一个简单且众所周知的模式可以避免静态初始化失败,在C++ FAQ Lite 的第 10.13 节中进行了描述。
在这个标准模式中,有一个权衡是构造的对象永远不会被破坏(如果析构函数没有重要的副作用,这不是问题)或者不能从另一个静态对象的析构函数安全地访问静态对象(请参阅C++ FAQ Lite 的 10.14 节)。
所以我的问题是:如果静态对象的析构函数具有最终必须发生的重要副作用并且静态对象必须由另一个静态对象的析构函数访问,那么您如何避免静态反初始化失败?
(注意:FAQ-lite 提到这个问题在C++ FAQs: FAQs 16.17 of C++ FAQs: FAQs by M. Cline and and and G. Lomow 中得到了回答。我无权阅读这本书,这就是我问这个问题的原因。 )
我试图制作类似Java风格的枚举,我称之为旗帜.要求是每个标志都是静态的,因此标志可以直接引用,每个标志存储其名称的字符串,整个集合可迭代并有助于查找.
我正在使用模板化,以便每组标志分开存储(从而使我不必在每个子类中明确地放置一个集合).
我确信这是一个启动问题,因为运行程序的成功或失败取决于包含标志声明的目标文件的文件名(Ao segfaults但Zo运行正常.)
问题似乎是静态初始化顺序之一,这个代码编译完全正常但是当它运行时,gdb产生以下内容:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff751e0fa in std::_Rb_tree_decrement(std::_Rb_tree_node_base*) ()
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/libstdc++.so.6
(gdb) bt
#0 0x00007ffff751e0fa in std::_Rb_tree_decrement(std::_Rb_tree_node_base*) ()
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/libstdc++.so.6
#1 0x0000000000462669 in operator-- ()
at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/include/g++-v4/bits/stl_tree.h:199
#2 _M_insert_unique ()
at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/include/g++-v4/bits/stl_tree.h:1179
#3 insert () at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/include/g++-v4/bits/stl_set.h:411
#4 Flag () at include/../util/include/Flag.hpp:34
#5 ItemFlag () at include/Item.hpp:22
#6 __static_initialization_and_destruction_0 () at Item.cpp:15
#7 global constructors keyed to _ZN3code8ItemFlag5brickE() () at Item.cpp:86
#8 0x000000000046ac62 in ?? ()
#9 0x00007fffffffddc0 in ?? ()
#10 0x000000000046abb0 in …Run Code Online (Sandbox Code Playgroud) 如果我有
atomic<int> cnt=0;
int get_int() noexcept
{
cnt++;
return rand();
}
Run Code Online (Sandbox Code Playgroud)
然后:
void func()
{
static const auto value = get_int();
}
Run Code Online (Sandbox Code Playgroud)
我知道初始化时没有竞争条件value,但我不知道是否
get_int()会被调用一次,或者在我的例子中将cnt是1(而不是2,3,4或5).
假设多个线程进入func()并且get_int只有一个呼叫站点func().
我最近遇到了一个奇怪的情况.
让我们考虑以下课程(放入header.h):
#ifndef HEADER_H
#define HEADER_H
#include <set>
template <class V, class T>
class Class
{
public:
typedef std::set<const Class<V, T>* > instances_list;
explicit Class(const V& Value):m_value(Value)
{
s_instances.insert(this);
}
private:
static instances_list s_instances;
V m_value;
};
template <typename V, typename T>
typename Class<V,T>::instances_list Class<V,T>::s_instances;
class Something : public Class<int, Something>
{
public:
static const Something SOMETHING_CONSTANT;
private:
explicit Something(int value): Class<int, Something>(value)
{}
};
#endif
Run Code Online (Sandbox Code Playgroud)
以及使用它的非常简单的应用程序:
#include "header.h"
const Something Something::SOMETHING_CONSTANT (1);
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
编译它会产生不同程度的成功. …
我们知道局部静态变量初始化在 C++11 中是线程安全的,现代编译器完全支持这一点。(在 C++11 中局部静态变量初始化线程安全吗?)
使其线程安全的成本是多少?我知道这很可能依赖于编译器实现。
上下文:我有一个多线程应用程序(10 个线程)通过以下函数以非常高的速率访问单例对象池实例,我担心它的性能影响。
template <class T>
ObjectPool<T>* ObjectPool<T>::GetInst()
{
static ObjectPool<T> instance;
return &instance;
}
Run Code Online (Sandbox Code Playgroud) 考虑以下带有两个静态成员变量的类片段:
public static class Foo
{
static string A = GetA(B);
static string B = "required for A";
...
Run Code Online (Sandbox Code Playgroud)
现在,我的理解是,A和B会在第一次访问时初始化。然而,当我执行上面代码片段的完全实现版本(在初始化A之前访问过的代码片段)时,它导致被传递到而不是. 为什么行为不是开始初始化A,然后,当它意识到需要初始化时,初始化,然后返回以完成初始化?BnullGetA()"required for A"BABA
这方面的一般规则是什么?为什么它会这样?我见过其他涉及此问题的问题(When do static Variables get initialized in C#?),但它们没有准确回答这个问题。C#中静态变量初始化顺序是什么?主要讨论它是如何跨类工作的,而不是在单个类中工作(尽管乔恩·斯基特对他的答案进行了补充——“根据大众的要求,当我认为问题是关于类中静态变量的初始化顺序时,这是我最初的答案:....”确实回答了这个问题,它被隐藏在一个更长的答案中)。
我在互联网上找到的所有关于静态初始化顺序惨败的内容都是关于 C++ 的,但是如果我初始化某种类型 Foo 的全局变量(例如
struct Foo {
int flag;
pthread_key_t key;
void *ptrs[10];
};
Run Code Online (Sandbox Code Playgroud)
我无法初始化类型变量,struct Foo如static struct Foo x = { 0 };?如果我想因为 SIOF 获得正确的代码?
在Java中,我可以创建一个List并立即使用静态初始化程序填充它.像这样的东西:
List <String> list = new ArrayList<String>()
{{
Add("a");
Add("b");
Add("c");
}}
这很方便,因为我可以动态创建列表,并将其作为参数传递给函数.像这样的东西:
printList(new ArrayList<String>()
{{
Add("a");
Add("b");
Add("c");
}});
我是C#的新手,并试图弄清楚如何做到这一点,但我是空洞的.这可能在C#中吗?如果是这样,怎么办呢?
我无法弄清楚为什么会这样.我正在使用一堆非常复杂的结构,联合,两者的未命名版本,静态变量等......但我确信这应该有效.经过一天的调试,我已经将问题缩小到以下代码中发生的情况.我正在使用-fms-extensions,这似乎不适合这种情况:
//main.c
//Why does y get set to 0 in the case of 'Breaks'?
//Compile with gcc -fms-extensions main.c
#include <stdio.h>
struct Base {
int x;
int y;
};
struct Extend {
union {
int X;
struct Base;
};
};
struct AlsoExtend {
struct Base;
int z;
};
static struct Extend Works = {
.x = 5,
.y = 3,
//.X = 2
};
static struct Extend Breaks = {
.x = 5,
.y = 3,
.X = 2
}; …Run Code Online (Sandbox Code Playgroud) 我想知道如下所示的Java中的静态初始化程序是否是一个为实现该语言而构建的groovy.
public class className{
static{
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢.