内存管理,拆开讲就是对如何将数据存储到内存中,如何释放内存中的数据,什么时候释放。
内存中的六大区域
内存分为5个区域,分别指的是----->栈区/堆区/BSS段/数据段/代码段
栈:存储局部变量,当其作用域执行完毕之后,就会被系统立即收回
堆:存储OC对象,手动申请的字节空间,需要调用free来释放
BSS段:未初始化的全局变量和静态变量,一旦初始化就会从BSS段中回收掉,转存到数据段中
数据段:存储已经初始化的全局变量和静态变量,以及常量数据,直到结束程序时才会被立即收回
常量区:存放常量字符串,程序结束后由系统释放
代码段:存放函数的二进制代码,直到结束程序时才会被立即收回
(以上摘自文档)
就我而言,经常搞混堆区,栈区的区别。在此做一个总结。
栈区:向低字节扩展的数据结构,是一块连续的内存区域,栈顶的地址和栈的容量(iOS中是1M)是系统预先规定好的。栈的内存管理由编译器自动管理,不需要我们操心。栈是FILO的队列,一一对应,不存在出现堆会出现的碎片问题。栈的分配方式:静态分配和动态分配。静态分配由编译器完成,比如局部变量的分配。动态分配由alloc函数进行分配。栈的动态分配也是由编译器释放,不需要我们手动实现。一个线程会分配一个栈。
什么时候会通过栈区来分配?
①NSObject *obj = [[NSObject alloc] init];
系统会在栈区存储obj对象的指针变量,指向堆区存储的obj对象。通过alloc函数,在堆区开辟一块内存空间,并生成NSObject内存结构的布局。
②int a = 1; int b = 2;
非对象的基本数据类型都是存放在栈中的。
所以,我们谈的内存管理,仅仅是针对OC对象而言的。基本数据类型是不需要我们去管理内存的。
③main{
int b; 栈区
char s[] = "abc" 栈
char *p1; 栈
char *p2 = "123456"; 123456\\\\0在常量区,p2在栈上。
static int c =0; 全局(静态)初始化区
w1 = (char *)malloc(10);
w2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
}
(摘自博客https://www.jianshu.com/p/f3c1b920e8eb)
堆区:向高地址扩展的数据结构,是不连续的内存区域。系统是用链表来存储空闲内存地址的。大量的new/delete会造成空间上的不连续,造成大量的碎片。
全局区(静态区) (static) :全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量存放在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域,程序结束后有系统释放。
注意:全局区又可分为未初始化全局区:BSS段和初始化全局区:数据段。
举例:int a;未初始化的。int a = 10;已初始化的。
例子代码:
int a = 10; 全局初始化区
char *p; 全局未初始化区
(摘自博客https://www.jianshu.com/p/f3c1b920e8eb)
比如static int a;BSS段 static int a = 10;数据段
假如static int a = 0; 这种情况呢?初始化了,但是初始化为0。
BSS段在程序执行之前会清0,所以未初始化的全局变量(静态变量)已经是0了。所以这种情况还是存放在BSS段。
关于全局变量与静态全局变量的定义与区别。
http://blog.csdn.net/mango_ios/article/details/52686892
以下数据和变量都存储在那一类内存中?
int a;int c = 10;
NSString *name1;NSString *name2 = @"lxx";
- (void) interviewForStore
{
int b;
NSString *name3 = @"hyc";
NSString *name4;
char h[] = "plm";
static int k = 0;
NSString *m = [[NSString alloc]initWithFormat:@"le"];
}
另:
野指针:指向垃圾内存(不可用内存)的指针。是非常危险的。
野指针具体是什么?
举例:Animal *ani = [[Animal alloc] init];//这句代码表示,初始化一个Animal对象在堆中,栈中有个指针ani指向该Animal对象。
[ani setAge:10];//这句话表示给指针ani指向的Animal对象发送一条消息:setAge:。
[ani release];//这句话表示给指针ani指向的Animal对象发送一条消息:release。即在堆中销毁。
[ani setAge:7];//给ani指向的Animal对象发消息。但是此时Animal对象已经被销毁了,ani指向的是不可用的内存。继续去访问这块内存。就会报野指针错误。ani就是野指针
僵尸对象:一个已经被释放的对象 就叫做僵尸对象.
内存回收的本质.
1.申请一块空间,实际上是向系统申请一块别人不再使用的空间.
2.释放一块空间,指的是占用的空间不再使用,这个时候系统可以分配给别人去使用.
3.在这个空间分配给别人之前 数据还是存在的.
3.1.OC对象释放以后,表示OC对象占用的空间可以分配给别人.
3.2.但是再分配给别人之前 这个空间仍然存在 对象的数据仍然存在.
4.僵尸对象: 一个已经被释放的对象 就叫做僵尸对象.
思考:以下数据和变量都存储在哪类内存中?
int a;int c = 10;
NSString *name1;NSString *name2 = @"lxx";
- (void) interviewForStore
{
int b;
NSString *name3 = @"hyc";
NSString *name4;
char h[] = "plm";
static int k = 0;
NSString *m = [[NSString alloc]initWithFormat:@"le"];
}