iOS中C++静态全局变量的动态初始化时序

简介: 一个由于C++初始化失败导致Realm初始化失败的Crash

日志

+ (void)load
{
    [RLMRealm defaultRealm];
}
// Global realm state
static std::mutex& s_realmCacheMutex = *new std::mutex();

......

RLMRealm *RLMGetThreadLocalCachedRealmForPath(std::string const& path) {
    std::lock_guard<std::mutex> lock(s_realmCacheMutex);  // <--- Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
    return [s_realmsPerPath[path] objectForKey:(__bridge id)pthread_self()];
}

最终的报错位置在这里,可以看出s_realmCacheMutex是一个空对象,能看出是初始化出了问题。

可是为什么没有初始化成功呢?

C++的静态初始化与动态初始化

  1. static initialization: 静态初始化指的是用常量来对变量进行初始化,主要包括 zero initialization 和 const initialization,静态初始化在程序加载的过程中完成,对简单类型(内建类型,POD等)来说,从具体实现上看,zero initialization 的变量会被保存在 bss 段,const initialization 的变量则放在 data 段内,程序加载即可完成初始化,这和 c 语言里的全局变量初始化基本是一致的。
  2. dynamic initialization:动态初始化主要是指需要经过函数调用才能完成的初始化,比如说:int a = foo(),或者是复杂类型(类)的初始化(需要调用构造函数)等。这些变量的初始化会在 main 函数执行前由运行时调用相应的代码从而得以进行(函数内的 static 变量除外)。

需要明确的是:静态初始化执行先于动态初始化! 只有当所有静态初始化执行完毕,动态初始化才会执行。

Objective-C的静态库与动态库

静态库与动态库的区别在于:

一、静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。

二、动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。

如果你在CocoaPods中使用了use_frameworks!,则Pods会将依赖库都打包成动态库

加载时序

静态库 + (void)load -> C++静态全局变量的动态初始化 -> 动态库 + (void)load -> main()

原因

不少人应该都猜出原因了吧,正是由于我在静态库的Load中初始化了Realm,导致Realm在获取互斥锁的时候出现了初始化失败。

解决方案

  1. 在+ (void)load中添加一个GCD异步任务,在异步中初始化Realm,此时GCD会将任务推迟到main之后执行。
  2. 改用动态库。
  3. 将Realm初始化延后。

参考资料

c++ 全局变量初始化的一点总结

目录
相关文章
|
2月前
|
存储 编译器 C++
【C++】深入探索类和对象:初始化列表及其static成员与友元(一)
【C++】深入探索类和对象:初始化列表及其static成员与友元
|
6月前
|
编译器 C语言 C++
C++一分钟之-C++11新特性:初始化列表
【6月更文挑战第21天】C++11的初始化列表增强语言表现力,简化对象构造,特别是在处理容器和数组时。它允许直接初始化成员变量,提升代码清晰度和性能。使用时要注意无默认构造函数可能导致编译错误,成员初始化顺序应与声明顺序一致,且在重载构造函数时避免歧义。利用编译器警告能帮助避免陷阱。初始化列表是高效编程的关键,但需谨慎使用。
75 2
|
3月前
|
编译器 C++
C++ 类构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
81 30
|
2月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
44 3
|
2月前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
55 3
|
2月前
|
C++
【C++】深入探索类和对象:初始化列表及其static成员与友元(二)
【C++】深入探索类和对象:初始化列表及其static成员与友元
|
2月前
|
编译器 C++
【C++】深入探索类和对象:初始化列表及其static成员与友元(三)
【C++】深入探索类和对象:初始化列表及其static成员与友元
|
7月前
|
存储 C++
C++程序全局变量:理解与应用
C++程序全局变量:理解与应用
113 0
|
2月前
|
C++
C++构造函数初始化类对象
C++构造函数初始化类对象
26 0
|
4月前
|
Dart API 开发工具
Dart ffi 使用问题之Dart API要在C++中使用,该如何初始化
Dart ffi 使用问题之Dart API要在C++中使用,该如何初始化