zoukankan      html  css  js  c++  java
  • 栈 & 堆 |--> 内存管理

    内存管理:

    栈区 [stack]:由编译器自动分配并释放,一般存放函数的参数值,局部变量等

     

    堆区 [heap]:程序员分配和释放,如果程序员不释放,程序结束时,可能会由操作系统回收

     

    全局区(静态区) [static]:全局变量静态变量的存储是放在一起的,初始化的全局变量和静态变量存放在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域,程序结束后由系统释放

     

    文字常量区:存放常量字符串程序结束后由系统释放

     

    程序代码区:存放函数的二进制代码

    官方文档:

    iOS开发中:

    内存分析

    1. 静态分析(Analyze)

    不运行程序, 直接检测代码中是否有潜在的内存问题(不一定百分百准确, 仅仅是提供建议)

    结合实际情况来分析, 是否真的有内存问题

     

    2. 动态分析(Profile == Instruments)

    1> 运行程序, 通过使用app, 查看内存的分配情况(Allocations)

    * 可以查看做出了某个操作后(比如点击了某个按钮显示了某个控制器), 内存是否有暴增的情况(突然变化)

     

    2> 运行程序, 通过使用app, 查看是否有内存泄漏(Leaks)

    * 红色区域代表内存泄漏出现的地方

    内存使用注意

    1. 加载小图片使用频率比较高的图片

    1> 利用imageNamed:方法加载过的图片, 永远有缓存, 这个缓存是由系统管理的, 无法通过代码销毁缓存

     

    2. 加载大图片使用频率比较低的图片(一次性的图片, 比如版本新特性的图片)

    1> 利用initWithContentsOfFile:imageWithContentsOfFile:imageWithData:等方法加载过的图片, 没有缓存, 只要用完了, 就会自动销毁

    2> 基本上, imageNamed:方法以外, 其他加载图片的方式, 都没有缓存

    PS:--关于图片资源

    1> 会压缩到Assets.car文件, 没有直接暴露在沙盒的资源包(main Bundle)

    * 条件 : "Deployment Target >= 7.x" 并且是 "放在Images.xcassets里面的所有图片"

    * 影响 : 无法得到图片的全路径, 只能通过图片名(imageNamed:方法)来加载图片, 永远会有缓存

     

    2> 不会压缩到Assets.car文件, 直接暴在沙盒的资源包(main Bundle)

    * 条件 : 1> 以外的所有情况

    * 影响 : 可以得到图片的全路径, 可以通过全路径(imageWithContentsOfFile:方法)来加载图片, 不会有缓存

    三. 如何让程序尽量减少内存泄漏

    1. ARC--MRC

    * Foundation对象(OC对象) :

      只要方法中包含了alloc ewcopymutableCopy etain等关键字,

      那么这些方法产生的对象, 就必须在不再使用的时候调用1release或者1autorelease

    * CoreFoundation对象(C对象) :

      只要函数中包含了create ewcopy etain等关键字,

      那么这些方法产生的对象, 就必须在不再使用的时候调用1CFRelease或者其他release函数

     

    2. ARC(只自动管理OC对象, 不会自动管理C语言对象)

    * CoreFoundation对象(C对象) :

      只要函数中包含了create ewcopy etain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1CFRelease或者其他release函数

    * 利用__bridge桥接,告诉编译器 管理c语言对象。

     

    3. block的注意--见:block详解!

    // block的内存默认在栈里面(系统自动管理)
    
    void (^test)() = ^{
    
    };
    // 如果对block进行了Copy操作, block的内存会迁移到堆里面(需要通过代码管理内存)
    
    Block_copy(test);
    // 在不需要使用block的时候, 应该做1次release操作
    
    Block_release(test);
    
    [test release];

    --------------------

    :由系统自动分配  --系统自动分配,速度较快 [ FIFO ]

    栈区结构:链表 or 数组

    :栈是向低地址扩展的数据结构,是一块连续的内存的区域,栈顶的地址和栈的最大容量是系统预先规定好的iOS中,主线程栈的大小是1M

     

    --[ 栈区:申请内存后响应 ]

    栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出

     

    --存储的内容

    栈:变量名(不带*)相当于是指向栈区数据的指针别名,变量名可以简化程序员的工作

     

     

    --------------------

    :需要程序员自己申请,alloccopy  --是由alloc分配的内存,速度比较慢,而且容易产生内存碎片,不过用起来最方便 [ LIFO ]

    堆区结构:树 or 链表

    :堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大

     

    --[ 堆区:申请内存后响应 ]

    堆:

    1. 操作系统有一个记录空闲内存地址的链表

    2. 当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序

    3. 由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表

     

    --存储的内容

    堆:要访问堆区中的数据,必须通过指针的方式才可以进行,指针的类型决定了访问堆中数据的方式

     

    --堆区的操作!

    1、操作系统以匿名(只记录内存地址和大小,不记录具体类型)的方式记录已经分配的内存区域

     

    2、当某一内存区域不再使用时,程序需要通知操作系统回收该内存区域,从而可以保证该内存区域被其他程序再次使用,否则,该区域将永远无法被再次分配,这就是传说中的内存泄露

     

    3、如果某一区域已经被释放仍然视图访问该区域,会提示坏内存访问,这就是传说中的野指针访问

     

     

    --------------------

    总结:

    1、我们程序员只需要关心堆区的内存管理,而栈区系统会自动回收。

    2、栈区存放的局部变量,出了作用域就会被销毁!

    3、内存结构中的其他几个分区,跟程序同生死:程序启动时,被加载到内存中;程序摧毁,内存被回收!

     

    PS:在iOS开发中:

    1> 堆区的内存是所有应用程序共享的,问题:内存泄露 & 野指针

      |--> 内存泄漏:如果程序员使用变量后,不释放内存(有强指针指向它),该内存区域会永远被占有,别的Application无法使用,即内存警告

      |--> 内存溢出(Out Of Memory)内存不够使用了,数据长度比较小的数据类型 存储了 数据长度比较大的数据类型

      |--> 野指针:当对象已经释放,程序中变量的指针依然指向该内存地址,如果再向该对象发送消息,就会报“野指针”错误

    2> 堆区的内存分配是由系统负责的。

    3> 系统是使用一个链表来维护所有已经分配过的内存空间。(见:上边--堆区:申请内存后响应)

    4> 系统只是记录分配了多少字节给应用程序,并不管理具体的类型-->“匿名”:只是记录分配的内存大小,不管具体是哪个类的!

    5> 如果变量使用结束后,需要释放内存,OC中当一个变量的引用计数==0时,说明没有变量使用这块内存空间,即系统直接回收

     

    -------

    分享:

    数据结构&算法分析 PDF,下载:Download 

     

    ----------- 

     

    |--> Copyright (c) 2015 Bing Ma.

    |--> GitHub RUL: https://github.com/SpongeBob-GitHub

     



    " There's always more to learn, and there are always better ways to do what you've done before. " -- Trybst


  • 相关阅读:
    Opengl绘制我们的小屋(二)第一人称漫游
    C# this.Invoke和this.BeginInvoke 最简单的写法
    C# 递归模型定义。赋值
    .net Core 2.1 后 Session保存,新页面获取不到值
    .net core mvc 错误信息显示 ModelState.AddModelError
    .net Core 依赖注入 Add********说明
    C# 中2个问号的作用。C#的??代表是什么意思
    asp.net mvc 加三层架构 完美搭配
    C# DataTable.Compute()用法
    C# DateTime判断时间
  • 原文地址:https://www.cnblogs.com/Trybst/p/4507900.html
Copyright © 2011-2022 走看看