C++全局对象的初始化顺序问题思考

问题产生:

  在代码中的某个头文件定了几个全局的 const std::string ,同时定义了某个类,在类的构造函数中使用了这几个全局变量。

该类作为单例模板的成员被使用了,单例的编译在另外一个单元。

程序编译链接正常,运行时候segment fault

gdb调试const 成员变量,内存不可访问

分析该问题需要具备的基础知识:

知识一:

全局变量文件域的静态变量类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化

局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象。

知识二:

对于出现在同一个编译单元内的全局变量来说,它们初始化的顺序与他们声明的顺序是一致的(销毁的顺序则反过来),而对于不同编译单元间的全局变量,c++ 标准并没有明确规定它们之间的初始化(销毁)顺序应该怎样,因此实现上完全由编译器自己决定,一个比较普遍的认识是:不同编译单元间的全局变量的初始化顺序是不固定的,哪怕对同一个编译器,同一份代码来说,任意两次编译的结果都有可能不一样。

问题解决:

方案一:

使用宏替换了const变量

方案二:

由于这几个常量只在定义的类中用到,放在了类成员里。

对于该问题,可以参考google C++编码规范的描述:

class 类型的全局变量是被禁止的,内建类型的全局变量是允许的,当然多线程代码中非常数全局变量也是被禁止的。永远不要使用函数返回值初始化全局变量。
不幸的是,全局变量的构造函数、析构函数以及初始化操作的调用顺序只是被部分规定,每 次生成有可能会有变化,从而导致难以发现的 bugs
因此, 禁止使用 class 类型的全局变量(包括 STL 的 string, vector 等等) ,因为它们的初始化顺序有可能导致构造出现问题。
内建类型和由内建类型构成的没有构造函数的结构体可以使用,如果你一定要使用 class 类型的全局变量,请使用 单件模式( singleton pattern)
对于全局的字符串常量,使用 C 风格的字符串,而不要使用 STL 的字符串:
const char kFrogSays[] = "ribbet";
虽然允许在全局作用域中使用全局变量,使用时务必三思。大多数全局变量应该是类的静态 数据成员,或者当其只在.cc 文件中使用时,将其定义到不具名命名空间中,或者使用静态
关联以限制变量的作用域。 记住,静态成员变量视作全局变量,所以,也不能是 class 类型!

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值