zoukankan      html  css  js  c++  java
  • ARC 下面可能导致的内存问题

    一、ARC相对MRC来说,减轻了程序员的大部分内存管理工作,使用ARC的时候也需要十分清除内存管理的原理,不然可能带来一些很难调试的问题。下面是ARC下面需要注意的一些问题

      1)对象互相引用,形成引用循环。引用循环是基于引用计数无法避免的问题,因为Objetive-C实质上还是一种编译时期的内存管理技术,没有引入GC,所以引用循环问题还是需要程序员手工处理。

        具体的处理办法就是使用weak,assign,_unsafe_unretained 修饰变量,打破引用循环。

        对象引用循环可能导致的问题,对象持久不释放,比如内存中存在两个VC,收到通知时,同一个方法执行两次等诡异的现象(大部分人通知的移除放在dealloc里面,放在viewWillAppear中可以避免此问题,但也可能引入更多问题)。

      2)使用ARC的时候,小心处理assign修饰的对象,assign只是简单的赋值,不对对象的引用计数做改变,对象释放了,这个assign记录的对象地址还是不变。向这个对象发送消息的时候,会偶先Crash。

        如果这个对象释放之后,对象内存区域数据,还是没有变化,是不会crash的。

        这一类crash是偶先的,有可能crash极难重现,想要暴漏这些问题,尽量不要使用assign、_unsafe_unretained ,而使用weak。

        有时候assign、_unsafe_unretained是无法避免的,例如NSNotification的observer,KVO的observer,NSValue valueWithNonretainedObject;

        还有可能是因为历史遗留代码中使用到assign、_unsafe_unretained。

      3)多线程传递autoRelease对象可能引起Crash

        autorelease的对象使用一种延迟释放的技术,将对象暂时记录下来,当autorelease pool drain的时候,向对象发送release消息。

        autorelease跟runloop存在一定的联系,runloop的每一次循环中,会默认创建一个autoreleasepool,因此如果在一个线程中,没有创建runloop并且没有创建autoreleasepool,autorelease对象可能存在泄漏。

        跨线程传递一个autorelease对象的时候,有可能对象在原来的线程中被提前释放掉。

        例如下面的代码:

        由于参数没有retain,有可能autorelease参数会被提前释放

    - (id) method
    
    {
        
         NSInvocation *invocation = [nsinvocation alloc] initWith ...
        //参数是autorelease的
         [invocation setArg:&[nsdata data] atIndex:index]
        //延迟调用
        invocation  performselector:@selector(invoke) afterdelay:
    
        
    }
    

        这里还有一个ARC下面的例子:

      

    23down voteaccepted

    I am guessing you are using ARC?

    The problem is with the line [invocation getReturnValue:&resultSet];getReturnValue: just copies the bytes of the return value into the given memory buffer, regardless of type. It doesn't know or care about memory management if the return type is a retainable object pointer type. Since resultSet is a __strong variable of object pointer type, ARC assumes that any value that has been put into the variable has been retained, and thus will release it when it goes out of scope. That is not true in this case, so it crashes. (Also, the array that you had resultSet originally point to will be leaked, since getReturnValue: overwrites that value without releasing it. Why you even made that variable point to an object in the first place is beyond me.)

    The solution is that you must give a pointer to a non-retained type to getReturnValue:. Either:

    NSArray * __unsafe_unretained tempResultSet;
    [invocation getReturnValue:&tempResultSet];
    NSArray *resultSet = tempResultSet;

    or:

    void *tempResultSet;
    [invocation getReturnValue:&tempResultSet];
    NSArray *resultSet = (__bridge NSArray *)tempResultSet;

    http://stackoverflow.com/questions/22018272/nsinvocation-returns-value-but-makes-app-crash-with-exc-bad-access

    二、MRC 自动转换为ARC是否会引起Crash

      有可能存在这样的情况,请见博客 《ARC下面的对象被释放的bug》

     

      

      

  • 相关阅读:
    网络编程
    网络编程
    网络编程
    Java——倒序输出Map集合
    java——assert(断言)方法
    Linux文件列表查询ll和ls区别
    Java——关键字和保留字
    Java——动态创建Class(不写入文件,直接从内存中创建class)
    web项目——启动时tomcat报错:Server Tomcat v7.0 Server at localhost failed to start.
    eclipse——管理远程资源的缓存,例如从Internet下载的资源。
  • 原文地址:https://www.cnblogs.com/doudouyoutang/p/4552378.html
Copyright © 2011-2022 走看看