news 2026/4/23 13:39:09

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
静态初始化顺序灾难(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

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/9 23:38:41

印度股市数据集成指南:利用 StockTV API 快速接入 NSE/BSE 实时行情

印度作为全球增长最快的主要经济体之一,其证券交易所(NSE 和 BSE)吸引了大量国际量化交易者和金融科技开发者。通过 StockTV API,您仅需使用 countryId14 即可轻松调取涵盖 Nifty 50 指数、数千只个股以及 IPO 日历在内的全维度金…

作者头像 李华
网站建设 2026/4/16 15:50:42

多智能体(Multi-Agent)架构选型:四种模式,一张图看懂

多智能体(Multi-Agent)架构选型:四种模式,一张图看懂 摘要(先看结论) 多智能体不是“更高级”,而是用更高的系统复杂度换取:上下文隔离、并行化、分工协作、长流程可控。 仍然能用“…

作者头像 李华
网站建设 2026/4/16 17:27:22

提示工程架构师的效率提升:深度学习Prompt自动优化工具

从“试错师”到“指挥官”:深度学习如何让Prompt优化告别瞎猜?关键词:提示工程、Prompt自动优化、深度学习、生成式AI、效率提升、强化学习、评估指标 摘要:在生成式AI时代,Prompt是连接人类需求与AI能力的“翻译器”&…

作者头像 李华
网站建设 2026/4/23 9:50:20

<span class=“js_title_inner“>第149篇:基于机器学习的字符N-Gram与 XGBoost模型的DGA恶意域名高效识别方法讲解</span>

Part1 前言 大家好,我是ABC_123。前面几期分享了几篇关于机器学习/深度学习/神经网络学习的文章,没想到自己在2016、2017年时的一些研究,在人工智能备受关注的当下,使得自己还没有掉队。当年在识别DGA域名的任务时,主要…

作者头像 李华
网站建设 2026/4/23 9:45:28

关于Locust的讲解

1. 它是什么Locust 是一个用 Python 编写的开源负载测试工具。它的核心思路是让你用普通的 Python 代码来定义测试用户的行为。你可以把 Locust 想象成一个“虚拟用户生成器”,这些虚拟用户会按照你编写的脚本,去操作你的网站或服务,以此来模…

作者头像 李华
网站建设 2026/4/23 9:47:21

提升仓储管理效率,其实没您想的那么难

对于制造企业而言,仓库从来不是简单的“物料堆放地”,而是串联生产、供应、交付的核心枢纽——仓库作业效率低,会直接导致交货延迟、成本攀升,甚至影响企业口碑,拖累整体发展。很多企业明明投入了人力、物力&#xff0…

作者头像 李华