iOS程序所占的内存分区
-
栈区:
- 存放函数的参数值,局部变量的值,基本数据类型等
- 由编译器自动分配释放,不需要程序猿管理栈内存
- 存放的数据变量遵循先进后出,且栈地址是从高到低分配
-
堆区:
- OC中用alloc函数生成的对象都是放在堆区
- 堆区的内存一般由程序猿进行释放,如果不释放,程序运行结束后由系统进行回收
- 堆区存放数据遵循先进先出,地址是从低到高
-
全局区/静态区(static):
- 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,
未初始化的全局变量和未初始化的静态变量在相邻的另一块区域, - 程序结束后由系统进行释放
- eg:int a;未初始化的。int a = 10;已初始化的
- 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,
-
常量区:
- 常量字符串就是放在这里的。 程序结束后由系统释放
-
代码区:
- 存放函数体的二进制代码
代码示例讲述
这是一个前辈写的,非常详细
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456\0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456\0放在常量区。
}
如下图所示:代码区存放于低地址,栈区存放于高地址,且区与区之间并不是连续的
注意事项:
- 在iOS中,堆区的内存是应用程序共享的,而堆区的内存分配是由系统负责的
- 当一个app启动后,代码区,常量区,全局区大小已固定,因此指向这些区的指针不会产
生崩溃性的错误。而堆区和栈区是时时刻刻变化的(堆的创建销毁,栈的弹入弹出),所
以当使用一个指针指向这两个区里面的内存时,一定要注意内存是否已经被释放,否则会
产生程序崩溃(也即是野指针报错)
堆区和栈区的比较
1.按照管理方式:
- 栈:系统编译器管理,不需要程序猿管理
- 堆:释放工作由程序员手动管理,不及时回收容易产生内存泄露
2.按照分配方式:
- 栈:静态分配和动态分配
- 静态分配:静态分配是系统编译器完成的,比如局部变量的分配
- 动态分配:动态分配是有alloc函数进行分配的,但是栈的动态分配和堆是不同的,它
的动态分配也由系统编译进行释放,不需要程序员手动管理
- 堆:堆是动态分配和回收内存的,没有静态分配的堆
堆区的一个例子
创建一个新的对象时,对象p指针存放在栈区,p将指向在堆区开辟的一块存储空间Person
在程序结束之前,p对象必须release,不然系统不知道释放堆区的Person内存。
如果p对象没有release,只是p=nil; 就是p指针指向了堆区地址为0的地方,那么原来的Person永远无法再次访问,而且也无法释放掉。
堆是所有程序共享的内存,当N个这样的内存得不到释放,堆区会被挤爆,程序立马瘫痪。这就是内存泄漏。
参考①:http://www.cnblogs.com/hangdada/p/4982989.html