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++ 全局变量初始化的一点总结

目录
相关文章
|
4天前
|
安全 数据安全/隐私保护 iOS开发
基于iOS的动态权限管理实现
【4月更文挑战第9天】 随着移动互联网的快速发展,用户对应用程序的隐私安全要求越来越高。在iOS平台中,如何实现动态权限管理成为了开发者关注的焦点。本文将详细介绍一种基于iOS的动态权限管理实现方法,通过使用Core Motion框架和Notification Center,实现对用户位置信息的实时监控和动态权限申请。
|
4天前
|
存储 算法 程序员
【C++20 新特性 】模板参数包展开与Lambda初始化捕获详解
【C++20 新特性 】模板参数包展开与Lambda初始化捕获详解
92 3
|
4天前
|
自然语言处理 编译器 C语言
【C++ 20 新特性】参数包初始化捕获的魅力 (“pack init-capture“ in C++20: A Deep Dive)
【C++ 20 新特性】参数包初始化捕获的魅力 (“pack init-capture“ in C++20: A Deep Dive)
46 0
|
4天前
|
安全 编译器 程序员
【C++ 修饰符关键字 explicit 】掌握C++中的explicit :构造函数行为和初始化综合指南
【C++ 修饰符关键字 explicit 】掌握C++中的explicit :构造函数行为和初始化综合指南
121 3
|
4天前
|
设计模式 算法 数据安全/隐私保护
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用(二)
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用
29 0
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用(二)
|
4天前
|
存储 算法 编译器
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用(一)
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用
71 0
|
4天前
|
存储 程序员 编译器
C++11:声明 & 初始化
C++11:声明 & 初始化
9 0
|
4天前
|
安全 程序员 编译器
【C++类和对象】初始化列表与隐式类型转换
【C++类和对象】初始化列表与隐式类型转换
|
4天前
|
编译器 C++ 容器
【C++11(一)】右值引用以及列表初始化
【C++11(一)】右值引用以及列表初始化
|
4天前
|
编译器 C++
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象