DEBUG问题-静态变量初始化顺序
问题
遇到问题的背景是:
我希望在全局变量定义的时候初始化一个全局变量:
就是这个_networker
我原先是这么写的:
这里就是一个简单的获取单例的函数。
然后在Networker的构造函数里面会有:
读取配置文件和Initialize函数,读取配置文件这里没什么问题我就不讲了。
关键在于初始化函数:
在初始化函数里面有某一段是这样的:
其中_OM是一个定义在cpp文件里面的全局变量:
OP_TYPE是一个枚举类型,存储着不同操作的类型。
而此时运行代码的时候,在第一个_OM初始化语句就报错了:
_OM[Util::StrHash("HEARTBEAT")] = OP_TYPE::HEARTBEAT;
报的是段错误,这时候我很纳闷?难道是hoscotch_map不支持枚举类型做值???看了一眼又发现其构造类型是泛型。但是这里一直在报错,并且我把全局变量改成Networker类的静态变量也会报错。
解决
后来才知道,原来全局变量和静态变量都存在静态区,而静态区的变量初始化顺序是随机的,也就是说在我执行到下面的代码的时候,这时候还没有进入main函数,也就是说程序此时还在随机的初始化所有的静态变量,而此时恰好_networker的初始化在_OM的前面,所以在initialize()执行的时候_OM还未初始化,所以导致了段错误。
shared_ptr<Networker> _networker = Networker::getSingleton();
其实我一开始问gpt的时候,gpt就给出了答案,只是我当时还不理解这个过程:
但此时gpt给出的答案是StrHash中用了没初始化的对象,但是方向对了,所以算半对吧。
这个问题是一个隐性bug,工作中碰到这样的bug很难发现,所以特此记录。
防御性编程
在编程的时候养成习惯,静态变量的初始化定义放在主程序的某个初始化函数中执行。
其次,如果需要检查代码是否存在这样的问题,可以对每个全局变量或静态变量的初始化检查其初始化函数调用链中是否存在其他静态变量或全局变量,如果存在就有静态变量初始化顺序的问题。