zoukankan      html  css  js  c++  java
  • OC 内存泄露 自动释放池

    花絮:看到下面的代码就想起这么一个调侃:

      一个老程序员,功成名就,金盆洗手不在写代码后,决定练练书法。提笔思索良久后在纸上写下:Hello world!

    /*********************************************************************************/

    1 首先说下自动释放池的底层实现

       它是通过以 AutoreleasePoolPage 为结点的双向链表来实现的。很类似栈的方式:对应push操作(底层是标记一个哨兵),这时相当于创建了一个自动释放池。当一个对象收到发送autorelease消息时,它被添加刚创建的自动释放池中,当自动释放池被回收时(对应pop操作),哨兵之后添加进来的对象从池中被删除, 并且会给它们发送release消息。则对象引用计数-1,如果为0则释放内存。很明显ARC相对于MRC,对象会延迟释放。

    2 举例

    有这么一段代码:largeNumber可以当做一个很大的数

    for (int i = 0 ; i < largeNumber; i++) {
        NSString *myStr = @"Hello world"; // 原谅我用Hello world
        myStr = [myStr stringByAppendingString:[NSString stringWithFormat:@"-%05d-",i]];
    }

      那么会有什么问题呢?

      如果largeNumber不大时没有问题,但是当它很大时问题非常严重!造成内存峰值。虽然ARC会自动释放内存,但是只有pop操作(完成一次runloop消息循环或@autoreleasepool {}结尾时)才会给池子里面的所有对象做一次release操作。

      当我们使用for循环创建很多个使用autorelease方式创建的NSString对象的时候,将所有的对象的释放权都交给了这个释放池,而这个释放池会等待完整的循环之后才有可能释放,因此就会使对象无法及时释放,堆积在内存造成内存峰值。

      代码应该这样修改:在循环内添加一个自动释放池,此时自动释放池就会处于当前线程的栈顶,那么每执行一次循环,就会新建一个自动释放池(push),循环结束进行一次(pop操作),那么添加在池子里面的对象就会被释放,则不会造成内存峰值。

    for (int i = 0 ; i < largeNumber; i++) {
        @autoreleasepool {
            NSString *myStr = @"Hello world";
            myStr = [myStr stringByAppendingString:[NSString stringWithFormat:@"-%05d-",i]];
        }
    }
  • 相关阅读:
    vue-element-admin项目install出现的问题
    关于html5 Notification桌面通知无法在谷歌浏览器显示的问题
    C#调用存储过程执行缓慢,但在数据库中执行却很快的问题
    IdnentiyServer-使用客户端凭据访问API
    IdentityServer开题篇
    IdentityServer4客户端JWT解密实现(基于.net4.0)
    iis访问网络路径映射问题(UNC share)
    .net core部署在iis上
    git blame 查找修改者
    代码管理工具-将项目文件打成tar包,并且排除.git目录
  • 原文地址:https://www.cnblogs.com/mddblog/p/4491576.html
Copyright © 2011-2022 走看看