iOS程序安装之后,是以Mach-o文件的格式保存在iOS设备里面,当启动程序时,对应的Mach-o文件就会被加载进内存。那么iOS程序的内存布局是什么样子的呢?
先上图:
代码区
- 该区是编译时分配的内存空间,在程序运行过程中,此内存中的数据一直存在,程序结束后由系统释放。
- 程序运行时的代码会被编译成二进制,存进内存的代码区域。
全局/静态区
- 该区是编译时分配的内存空间,在iOS中一般以0x1开头,程序运行过程中,此内存中的数据一直存在,程序结束后由系统释放。
- 未初始化的全局变量和静态变量,在BSS区,即未初始化区,.bss。
- 已初始化的全局变量和静态变量,在数据区,即初始化区,.data。
常量区
- 该区是编译时分配的内存空间,在程序运行过程中,此内存中的数据一直存在,程序结束后由系统释放。
- 存放常量:整型、字符型、浮点、字符串等。
堆区
- 是不连续的内存从低地址向高地址存储,遵循先进先出(FIFO)原则。
- 堆的地址空间iOSx86架构下以0X6开头,空间的分配是动态的。
- 需要关注变量的生命周期,不及时释放会造成内存泄露。
- OC中使用alloc、new开辟空间创建的对象内存放在堆区(而指向内存的指针还是在栈里)。
- C语言中使用malloc、calloc、realloc分配的空间,需要free释放。
栈区
- 是一段连续的内存区域,从高地址向低地址存储,遵循先进后出(FILO)原则。
- 在x86架构下,栈的地址一般为0X7开头。
- 一般在运行时进行分配,内存空间由系统管理,变量过了作用域范围后内存便会自动释放。
- 参数、函数、局部变量都放在栈区。
- 参数入栈是从前往后入栈。而结构体入栈是从后往前入栈。
栈区与堆区对比
- 栈是一段连续的内存区域,堆是不连续的内存
- 栈系统自动回收内存,堆需要开发人员手动释放
- 栈内存大小有限制,内存空间小,堆内存空间大
代码验证
int a = 1; //已初始化全局变量
int b; //未初始化全局变量
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
static int c = 2; //已初始化静态变量
static int d; //未初始化静态变量
int e; //未初始化局部变量
int f = 2; //已初始化局部变量
NSString *str = @"字符串常量";//字符串常量
NSObject *obj = [[NSObject alloc] init];//通过alloc动态分配(实例对象)
NSLog(@"\n&a=%p\n&b=%p\n&c=%p\n&d=%p\n&e=%p\n&f=%p\nstr=%p\nobj=%p\n",
&a, &b, &c, &d, &e, &f, str, obj);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
输出结果
&a=0x1052fd528
&b=0x1052fd534
&c=0x1052fd52c
&d=0x1052fd530
&e=0x7ffeea9061e4
&f=0x7ffeea9061e0
str=0x1052fc168
obj=0x6000019a8020
- 通过输出结果可以看到,a、b、c、d在全局/静态区,地址也确实已0x1开头;
- str=0x1052fc168 在常量区;
- e、f 是局部变量,在栈;
- obj=0x6000019a8020在堆;
这样就验证了开始的结论!!
- 面试基础
iOS面试基础知识 (一)
https://github.com/iOS-Mayday/heji
iOS面试基础知识 (二)
https://github.com/iOS-Mayday/heji
iOS面试基础知识 (三)
https://github.com/iOS-Mayday/heji
iOS面试基础知识 (四)
https://github.com/iOS-Mayday/heji
iOS面试基础知识 (五)
https://github.com/iOS-Mayday/heji
网友评论