访问类似singleton的静态成员的seg错误
seg fault for accessing a singleton-like static member
这是简化的代码。。。
//A class used in the next class, Nothing much to worry about
class BasicLogger{
//...
};
下面是我的主要课。它有两个成员:一个是它自己类型的静态成员(称为log
)。以及一个容器(称为repo
),用于容纳上述类的对象。使用operator[]
重载可以访问repo
的项目
class Logger {
protected:
// repository of profilers. each profiler is distinguished by a file name!
std::map<const std::string, boost::shared_ptr<BasicLogger> > repo;
public:
Logger(){} //breakpoints never reach here. why?
//universal singleton-like access to this class
static Logger log;
//returns a member stored in the above 'repo'
virtual BasicLogger & operator[](const std::string &key);
};
问题来自于这种方法:
BasicLogger & Logger::operator[](const std::string &key)
{
std::map<std::string, boost::shared_ptr<BasicLogger> >::iterator it = repo.find(key);
if(it == repo.end()){
std::cout << "creating a new Logger for " << key << std::endl;
boost::shared_ptr<BasicLogger> t(new LogEngine(key));
std::map<const std::string, boost::shared_ptr<BasicLogger> > repo_debug;//just for debug
repo_debug.insert(std::make_pair(key,t));//ok
repo.insert(std::make_pair(key,t));//seg fault
return *t;
}
return *it->second;
}
最后一条信息:在整个项目中,访问repo
容器中的项目如下。
namespace{
BasicLogger & logger = Logger::log["path_set"];
}
问题:
问题是,在程序开始时,在进行任何操作之前,控制直接进入BasicLogger & logger = Logger::log["path_set"];
Q1:为什么控制首先进入此处?仅仅因为log
是静态的,或者最初也参与了匿名命名空间?
无论如何,因此当执行运算符[]时,repo
似乎未初始化。我添加了一个具有与repo
相同签名的局部伪变量(repo_debug
)。并使用gdb:观察它们的值
//local repo_debug
Details:{... _M_header = {... _M_parent = 0x0, _M_left = 0x7fffffffdc08, _M_right = 0x7fffffffdc08}, _M_node_count = 0}}}
//main 'repo'
Details:{..._M_parent = 0x0, _M_left = 0x0, _M_right = 0x0}, _M_node_count = 0}}}
Q2。为什么repo
未初始化?基本上,为什么不调用Logger
的构造函数?
第三季度。非常感谢有关解决此问题的建议。感谢
Q1:假设声明在单独的编译单元中。编译单元之间的静态初始化顺序是由实现定义的。所以,这是因为偶然。我认为这是一个幸运的机会,因为从另一方面来说,你最初会认为它有效,但后来发现它在另一个cpu/编译器/os上坏了。
Q2:因为匿名命名空间中的logger
首先被初始化,导致segfault阻止静态log
初始化。
Q3.你可以通过在设计中避免单体来避免这个问题。但如果你想要singleton,避免静态初始化顺序失败的一种方法是构造第一次使用的习语:
Logger& Logger::log() {
static Logger* log = new Logger();
return *log;
}
缺点是动态分配的对象实际上从未被释放(无论如何,singleton都会在程序结束时被释放,但如果您在没有操作系统的情况下运行,这可能是一个问题)
静态局部初始化的线程安全性由§6.7/4(c++11草案)中的标准保证:
否则,这样的变量是在控件第一次通过其声明时初始化;这样的变量被认为是在完成其初始化。如果初始化通过抛出异常退出,则初始化未完成,因此将在下次控件进入声明时重试如果控制进入在初始化变量时并发声明,并发执行应等待初始化完成
在早期的标准和visual c++中,您可以通过确保至少在一个静态初始化期间调用的构造函数中调用log
来避免并发问题(这发生在主程序生成任何线程之前)。
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 为什么传递非静态成员函数会导致编译错误?
- 在 T 的静态成员中使用 sizeof(T) 的 c++ 错误
- 错误:无效使用非静态成员函数"int test::hotplug_callback(libusb_contex
- C :(不重复)积分静态成员初始化(不仅是声明!),导致链接器错误,原因
- 错误:在 C++ 中无效使用非静态成员函数
- C++类静态成员函数调用错误
- 结构内部的结构:"对非静态成员的非法引用"错误
- 在C 中,静态成员函数是否继承了?如果是,为什么没有出现歧义错误
- 在C 中获取Invalig使用非静态数据成员错误
- 非静态数据成员错误的使用无效
- gcc 和 clang 中 constexpr 静态成员变量的链接器错误
- C++ 线程函数指针实现返回错误无效使用非静态成员函数
- 错误:必须调用对非静态成员函数的引用 (2)
- C++ PTHREAD 错误:非静态成员函数的使用无效
- 私有静态成员 - 编译错误?
- 使用C ,使用SFINAE测试静态成员的存在,返回错误的值
- 我的错误,还是英特尔编译器的错误?非静态成员错误的大小
- c++中的静态成员错误
- 类模板的静态成员错误