背景描述:使用 Objective-C 开发 iOS 或者 MacOS 应用
具体会初始化和创建哪些全局变量 ?
在 iOS 应用程序的启动过程中,初始化和创建全局变量的步骤确实包含了多种类型的全局变量。具体来说,包含以下几种类型:
-
C 全局变量:
- 这些变量在程序加载时分配内存并初始化,生命周期与程序运行时一致。
-
C 静态全局变量:
- 这些变量与普通全局变量类似,但它们仅在声明它们的文件中可见。
-
C++ 全局变量:
- 这些变量在程序加载时分配内存,并调用其构造函数进行初始化。
-
C++ 静态全局变量:
- 类似于 C++ 全局变量,但它们仅在声明它们的文件中可见,并在程序加载时调用其构造函数进行初始化。
-
Objective-C 全局变量:
- 这些变量在程序加载时分配内存并初始化,生命周期与程序运行时一致。
-
Objective-C 静态全局变量:
- 类似于 C 静态全局变量,但用于 Objective-C 类型。
初始化顺序
初始化的顺序依赖于编译器和链接器的实现,但通常遵循以下顺序:
-
调用用
attribute((constructor))
修饰的函数:- 这些函数首先被调用,进行早期的初始化操作。
-
执行类和 Category 的
+load
方法:- 接下来,Objective-C 运行时会执行所有类和 Category 的
+load
方法。
- 接下来,Objective-C 运行时会执行所有类和 Category 的
-
初始化全局变量:
- 最后,初始化各种全局变量。这包括:
- C 和 C++ 全局变量:按定义顺序初始化。
- C 和 C++ 静态全局变量:按定义顺序初始化,但仅在声明文件中可见。
- Objective-C 全局变量:与普通全局变量类似,按定义顺序初始化。
- Objective-C 静态全局变量:按定义顺序初始化,但仅在声明文件中可见。
- 最后,初始化各种全局变量。这包括:
示例
// C 全局变量
int global_c_variable = 10;// C 静态全局变量
static int static_global_c_variable = 20;// C++ 全局变量
class MyClass {
public:MyClass() { /* 构造函数代码 */ }
};
MyClass global_cpp_variable;// C++ 静态全局变量
static MyClass static_global_cpp_variable;// Objective-C 全局变量
NSString *global_objc_variable = @"Hello";// Objective-C 静态全局变量
static NSString *static_global_objc_variable = @"World";
这些全局变量会在程序启动时依次初始化,确保它们在 main()
函数执行前已经准备就绪。这种初始化顺序和机制确保了应用程序在启动时的稳定性和一致性。
所有全局变量都是在 main() 函数执行前, 初始化和创建的么 ?
在 iOS 应用程序中,绝大多数全局变量确实都是在 main()
函数执行之前初始化和创建的。这包括 C、C++ 和 Objective-C 的全局变量和静态全局变量。这是因为在程序启动过程中,系统会先进行各种加载和初始化操作,以确保在 main()
函数开始执行时,所有需要的资源和状态都已经准备就绪。
全局变量初始化的顺序
-
加载可执行文件和动态链接库:
- 首先加载可执行文件和所有动态链接库,并进行重定位和符号绑定。
-
调用
attribute((constructor))
修饰的函数:- 这些函数在动态库加载后立即被调用,执行早期的初始化操作。
-
执行 Objective-C 类和 Category 的
+load
方法:- 在调用
main()
之前,Objective-C 运行时会调用所有类和 Category 的+load
方法,进行类级别的初始化。
- 在调用
-
初始化全局变量:
- 在这一步,所有全局变量(包括静态全局变量)都会被初始化。具体来说,包括:
- C 全局变量和静态全局变量:按照它们在代码中的定义顺序初始化。
- C++ 全局变量和静态全局变量:在加载时调用它们的构造函数进行初始化。
- Objective-C 全局变量和静态全局变量:按照定义顺序进行初始化。
- 在这一步,所有全局变量(包括静态全局变量)都会被初始化。具体来说,包括:
特殊情况
虽然上述流程适用于绝大多数情况,但在某些特定场景下,可能会有一些例外:
-
懒加载的变量:
- 某些全局变量可能会被设计为懒加载,即在第一次访问时才进行初始化。这种模式通常用于优化启动性能,减少不必要的初始化开销。
-
动态加载的库:
- 某些动态库可能在
main()
执行之后才会被动态加载和初始化(例如使用dlopen
动态加载库)。
- 某些动态库可能在
例子
以下是一个包含各种全局变量的示例:
// C 全局变量
int global_c_variable = 10;// C 静态全局变量
static int static_global_c_variable = 20;// C++ 全局变量
class MyClass {
public:MyClass() { /* 构造函数代码 */ }
};
MyClass global_cpp_variable;// C++ 静态全局变量
static MyClass static_global_cpp_variable;// Objective-C 全局变量
NSString *global_objc_variable = @"Hello";// Objective-C 静态全局变量
static NSString *static_global_objc_variable = @"World";// attribute((constructor)) 修饰的函数
__attribute__((constructor))
void early_initialization() {// 早期初始化代码
}// main 函数
int main(int argc, char * argv[]) {@autoreleasepool {// 程序的主要逻辑return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}
}
在这个示例中,所有的全局变量都会在 main()
函数执行之前进行初始化。early_initialization
函数会在全局变量初始化之前被调用,用于执行一些早期的初始化逻辑。
总之,大部分全局变量都是在 main()
函数执行之前初始化和创建的,以确保程序在启动时拥有正确的运行环境。
其它的情况,也会在 main() 函数执行前,初始化和创建
下文中变量的定义可能与上方冲突,但这不重要,关注具体的示例就行
在 Objective-C 开发的 iOS 应用中,冷启动时在 main()
函数执行前,系统会创建和初始化以下类型的变量:
1. C 静态全局变量
定义:在 C 语言中声明为 static
的全局变量。
链接范围:具有内部链接,只在声明它的翻译单元内可见。
生命周期:在程序开始时初始化,并在程序结束时销毁。
示例:
// MyGlobal.c
#include <stdio.h>static int myStaticGlobalVariable = 42; // 仅在 MyGlobal.c 内可见__attribute__((constructor))
static void initializeMyGlobal() {printf("Initializing C static global variable\n");
}
2. C 全局变量
定义:在 C 语言中未声明为 static
的全局变量。
链接范围:具有外部链接,可以在多个翻译单元中被引用(通过 extern
声明)。
生命周期:在程序开始时初始化,并在程序结束时销毁。
示例:
// MyGlobal.h
extern int myGlobalVariable;// MyGlobal.c
#include "MyGlobal.h"int myGlobalVariable = 42;__attribute__((constructor))
void initializeMyGlobal() {printf("Initializing C global variable\n");
}
3. C++ 静态全局变量
定义:在 C++ 中声明为 static
的全局变量。
链接范围:具有内部链接,只在声明它的翻译单元内可见。
生命周期:在程序开始时初始化,并在程序结束时销毁。其初始化顺序在同一个翻译单元内是定义的,但跨翻译单元的初始化顺序是未定义的。
示例:
// MyGlobal.cpp
#include <iostream>static int myCppStaticGlobalVariable = 42; // 仅在 MyGlobal.cpp 内可见__attribute__((constructor))
static void initializeMyGlobal() {std::cout << "Initializing C++ static global variable\n";
}
4. C++ 全局变量
定义:在 C++ 中未声明为 static
的全局变量。
链接范围:具有外部链接,可以在多个翻译单元中被引用(通过 extern
声明)。
生命周期:在程序开始时初始化,并在程序结束时销毁。
示例:
// MyGlobal.h
extern int myCppGlobalVariable;// MyGlobal.cpp
#include "MyGlobal.h"int myCppGlobalVariable = 42;__attribute__((constructor))
void initializeMyGlobal() {std::cout << "Initializing C++ global variable\n";
}
5. Objective-C 静态全局变量
定义:在 Objective-C 文件中声明为 static
的全局变量。
链接范围:具有内部链接,只在声明它的翻译单元内可见。
生命周期:在程序开始时初始化,并在程序结束时销毁。
示例:
// MyGlobal.m
#import <Foundation/Foundation.h>static int myObjCStaticGlobalVariable = 42; // 仅在 MyGlobal.m 内可见__attribute__((constructor))
static void initializeMyGlobal() {NSLog(@"Initializing Objective-C static global variable");
}
6. Objective-C 类静态变量
定义:在 Objective-C 类中声明的静态变量。
链接范围:具有内部链接,只在声明它的类内可见。
生命周期:在程序开始时初始化,并在程序结束时销毁。
示例:
// MyClass.h
#import <Foundation/Foundation.h>@interface MyClass : NSObject
+ (void)printStaticVariable;
@end// MyClass.m
#import "MyClass.h"@implementation MyClassstatic int myClassStaticVariable = 42;+ (void)printStaticVariable {NSLog(@"Class static variable: %d", myClassStaticVariable);
}@end