当前位置: 首页 > news >正文

静态初始化顺序灾难(Static Initialization Order Fiasco)

前言:童鞋们有没有遇到过程序已启动就莫名地崩溃了?很多时候SIOF(Static Initialization Order Fiasco)是罪魁祸首。今天来讲讲静态初始化顺序问题。

目录

一、先看个例子

二、初始化逻辑

2.1 静态初始化

2.2 动态初始化

三、如何避免

3.1 判断是否是全局初始化阶段导致的崩溃

3.2 推荐的解决措施


一、先看个例子

假如我们有一个全局单例,在logger.cpp文件中:

// logger.cpp class Logger { public: void log(const char* msg); }; Logger g_logger; // 全局对象

在另一个service.cpp文件中,使用了上面的g_logger全局对象:

// service.cpp extern Logger g_logger; class Service { public: Service() { g_logger.log("Service started"); } }; Service g_service;

童鞋们看出上面代码中的问题了吗?

在对g_service对象进行构造的时候,很容易导致崩溃!为什么呢?

如果g_looger对象先于g_service对象初始化,那么就是安全的。那如果g_logger对象初始化在后,那么可怕的崩溃就发生了!

这就是初始化顺序问题导致的灾难。对于上述两个对象初始化谁先谁后,其实是无法保证的,因为它们在两个不同的源文件中,编译器的链接顺序是不确定的。【注:在同一源文件中的全局对象,初始化是按照其定义顺序进行的】

二、初始化逻辑

C++把全局、静态变量(非局部)的初始化分为两种:

2.1 静态初始化

零初始化:内存清0

常量初始化:编译器就能够确定的常量表达式,如:

int num = 2; const double pi = 3.14159;

这类初始化是程序启动前就完成了,几乎不会产生什么问题。

2.2 动态初始化

运行时的初始化,如:

调用构造函数:如,第一节中列举的例子

函数返回值初始化:如

int num = caculate();

这类初始化在程序一启动时候执行(在主程序之前,如main())。如果不注意初始化顺序,很容易出现程序崩溃问题。

三、如何避免

3.1 判断是否是全局初始化阶段导致的崩溃

全局初始化阶段崩溃,一般调用栈会出现以下关键字眼:

_init_term、__static_initialization_and_destruction_* global constructors keyed to dynamic initializer for

3.2 推荐的解决措施

使用函数内的静态局部变量,其特点是:

  • 首次进入时才进行构造;
  • 初始化顺序由调用流决定;
  • 线程安全(C++11及之后)。

根据这个思想,将第一节中的代码 进行优化:

// logger.cpp class Logger { public: void log(const char* msg); }; Logger& getLogger() { static Logger m_log; //静态局部,首次调用时构造,线程安全(C++11) return m_log; }
// service.cpp class Service { Service() { getLogger().log("Service started"); // 此时保证 Logger 已初始化 } }; Service g_service; // 仍然可以是全局,但它内部访问的是函数内 static

这就简单、完美地解决了初始化顺序导致的崩溃灾难!

感兴趣的童鞋可关注作者公众号(定期同步)

http://www.jsqmd.com/news/334439/

相关文章:

  • 科技润田 智赋农耕,以数字力量激活农业新质生产力
  • Flutter 三端应用实战:OpenHarmony “心流之泉”——在碎片洪流中,为你筑一眼专注的清泉
  • SSM毕设项目:基于ssm的医院招聘考试管理系统的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 【毕业设计】基于ssm的医院招聘考试管理系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • RoPE-Matrix_昇腾亲和的RoPE算法实现与算子开源
  • 未买房,先赴宴!这家房企为何敢把“准业主”宠上天?
  • mos管跨导gm三种公式
  • C++中的策略模式进阶
  • 揭秘招商蛇口的“家宴经济学”:为何说这是一笔最划算的品牌投资?
  • 我的免费低代码选型笔记!五位搭档让我效率起飞
  • SSM计算机毕设之基于ssm的医院招聘考试管理系统的设计与实现信息发布、在线报名、考务管理、智能阅卷与数据统计(完整前后端代码+说明文档+LW,调试定制等)
  • CAN通信:STM32F1xx_hal_can入门实战详解
  • 【计算机毕业设计案例】基于ssm框架开发的在线考试管理系统设计与实现基于ssm的医院招聘考试管理系统的设计与实现(程序+文档+讲解+定制)
  • <span class=“js_title_inner“>当我和AI从意识自由聊到“它”(十一)</span>
  • Python函数定义与调用:编写可重用代码的基石
  • 2026年2月最新采购管理系统测评报告
  • 30 岁转行网络安全真的可行吗?过来人手把手教你避坑 + 从 0 到 1 学习指南
  • 一篇讲透2025程序员岗位分类和平均薪资!
  • Linux Shell(五)-- 正则表达式
  • 大额盒马鲜生礼品卡回收平台推荐 - 京顺回收
  • SecureCRT如何打开左侧边栏?
  • Google AI Agent 白皮书拆解(1):从《Introduction to Agents》看清 Agent 的工程底座
  • dw - --
  • 智能体来了(西南总部):AI Agent指挥官与AI调度官面对复杂系统
  • 印度股市数据集成指南:利用 StockTV API 快速接入 NSE/BSE 实时行情
  • 基于IEC 62368标准的鲁邦通边缘计算网关硬件架构与安全实践
  • “老板,之前咱TPS是100,我优化完是10000”
  • 实战分享:基于高EMC边缘计算网关的电力巡检机器人自主乘梯架构设计
  • Android Jetpack Compose - Color 的 copy 方法、FloatingActionButton、IconButton
  • 提示工程架构师的效率提升:深度学习Prompt自动优化工具