zoukankan      html  css  js  c++  java
  • 十二:内存简单介绍和OC的内存管理

    一、内存简单介绍

    内存结构

    1、运行时分配

    (1)栈:用户存放程序临时创建的局部变量(先进后出)。

    (2)堆:动态分配内存段。

    2、编译器分配

    (1)BSS段:存放未初始化的全局变量和静态变量。

    (2)数据段:已初始化的全局变量和静态变量。

    (3)代码段:执行代码的一块区域。

    地址由低到高:代码段 -> 数据段 -> BSS段-> 堆 -> 栈 

    内存分配方式

    1、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

    2、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

    3、从堆上分配,亦称动态内存分配。动态内存的生存期由程序员决定,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块。

    二、OC内存管理(iOS7.0后不用手动管理,可以了解相关原理)

    1、进行内存管理的原因:是由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等。

    2、内存管理范围:任何继承NSObject的对象,对其他的基本数据类型无效。

    本质原因是存储空间不一样,对象存储于堆中,而其它局部变量主要存放于栈中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对象已经没有指针指向,但依然存在于内存中,造成内存泄露。

    3、对象的基本结构:每个OC对象都有自己的引用计数器,是一个整数表示对象被引用的次数,即现在有多少东西在使用这个对象。对象刚被创建时,默认计数器值为1,当计数器的值变为0时,则对象销毁。

    在每个OC对象内部,都专门有4个字节的存储空间来存储引用计数器。

    引用计数器的作用:判断对象是否需要回收的唯一依据就是计数器是否为0,若不为0则存在。
    4、当给对象发送消息时,进行引用计数器操作

    Retain消息:使引用计数器+1,改方法返回对象本身

    Release消息:使引用计数器-1(并不代表释放对象)

    retainCount消息:获得对象当前的引用计数器值

    5、当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收。当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,书写格式如下:

    1 - (void)dealloc
    2 {
    3     [super dealloc] //必须调用必须调用调用此方法,且必须写在最后
    4 }

    6、注意事项:

    野指针错误:访问了一块坏的内存(已经被回收的,不可用的内存)。

    僵尸对象:所占内存已经被回收的对象,僵尸对象不能再被使用。(打开僵尸对象检测)

    空指针:没有指向任何东西的指针(存储的东西是0,null,nil),给空指针发送消息不会报错

    注意:不能使用[p retaion]让僵尸对象起死复生。

    7、内存管理原则

    (1)只要还有人在使用某个对象,那么这个对象就不会被回收。

       只要你想使用这个对象,那么就应该让这个对象的引用计数器+1。

       当你不想使用这个对象时,应该让对象的引用计数器-1。

    (2)谁创建,谁release

       如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法

       不是你创建的就不用你去负责

    (3)谁retain,谁release。只要你调用了retain,无论这个对象时如何生成的,你都要调用release。

    三、内存管理中的循环引用问题以及解决

    若使用#import的方式相互包含,就会形成了循环引用。这时可以使用一个@class来代替其中一个#improt来解决循环引用问题,提高性能!

    @class仅仅告诉编译器,在进行编译的时候把后面的名字作为一个类来处理。

    书写规范:@class 类名;

    作用:声明一个类,告诉编译器某个名称是一个类。

    具体用法:1、在.h文件中使用@class来声明类。

         2、在.m文件中真正要使用到的时候,使用#import来包含类中的所有东西。

         3、两端循环引用的解决方法:一端使用retain,一端使用assign(使用assign的在dealloc中也不用再release)。

  • 相关阅读:
    VS工作目录,输出目录
    Google的C++开源代码项
    C++文件读写
    深拷贝浅拷贝
    Efficient Graph-Based Image Segmentation
    Graph Cut 简介
    Graph Cut
    "GrabCut" - Interactive Foreground Extraction using Iter
    EM算法
    Python图像处理库(2)
  • 原文地址:https://www.cnblogs.com/hissia/p/5448410.html
Copyright © 2011-2022 走看看