记录一次内存泄漏排查历程

背景

  通过在deinit方法内打印日志,发现某个ViewController的deinit方法没有执行,决定排查下具体的原因。

方案1,instruments排查

  打开instruments,按照内存泄漏的流程进行检测,反复进入,退出目标ViewController,检查instruments法相并没有定位到内存泄漏的代码,为了保险起见,又参考了网上的检测流程反复多次进行检测,结果都是一样没有定位到内存泄漏的具体代码。

方案2:Xcode Analysis

  使用Xcode的Analysis 功能确实分析出来了一些内存泄漏的代码,但是和目标ViewController没有关系。

方案3, 代码注释法

通过对目标ViewController的代码不断进行注释,检查deinit方法是否会执行,不断缩小范围,最终定位到一行代码,如下:

 IZoneInterfaceiOS.sharedInstance()?.traceHandler = self

traceHandler的定义如下:

@property(weak, nonatomic) id traceHandler;

根据目前的信息看,一个被声明为weak的属性,不可能还会出现被持有不释放造成内存泄漏的情况。
继续排查使用的地方,发现只有一个地方进行了使用,代码如下:

void sdk_log_cb(SdkLogLevel level, const char* msg)
{
    NSString* log_msg = [NSString stringWithUTF8String:msg];
        if ([IZoneInterfaceiOS sharedInstance].traceHandler)
        {
            [[IZoneInterfaceiOS sharedInstance].traceHandler onTrace:(ZoneLogLevel)level log:log_msg];
        }
 }

将使用到traceHandler的代码注释掉,发现内存泄漏不存在了,注释掉以后的代码如下:

void sdk_log_cb(SdkLogLevel level, const char* msg)
{
    NSString* log_msg = [NSString stringWithUTF8String:msg];
       // if ([IZoneInterfaceiOS sharedInstance].traceHandler)
        //{
          //  [[IZoneInterfaceiOS sharedInstance].traceHandler onTrace:(ZoneLogLevel)level log:log_msg];
       // }
 }

然后把只注释掉如下代码:

void sdk_log_cb(SdkLogLevel level, const char* msg)
{
    NSString* log_msg = [NSString stringWithUTF8String:msg];
        if ([IZoneInterfaceiOS sharedInstance].traceHandler)
        {
          //  [[IZoneInterfaceiOS sharedInstance].traceHandler onTrace:(ZoneLogLevel)level log:log_msg];
        }
 }

分析可知,只要是在这个函数里用了traceHandler,就会产生内存泄漏,及时是仅仅打印traceHandler也会泄漏。后来验证了一下,确实如此。
仔细思考了发现这个函数是C,C++的函数,在执行的时候会对traceHandler默认执行retain操作,但是这个traceHandler是OC对象,释放需要OC来执行release操作,,但是ARC下已经不能手动执行release操作了。决定把这段代码放到自动释放池中,当执行完后,自动执行一下release操作。验证后发现确实如此,也解决了内存泄漏。修改后的代码如下:

void sdk_log_cb(SdkLogLevel level, const char* msg)
{
    NSString* log_msg = [NSString stringWithUTF8String:msg];
    @autoreleasepool {
        if ([IZoneInterfaceiOS sharedInstance].traceHandler)
        {
            [[IZoneInterfaceiOS sharedInstance].traceHandler onTrace:(ZoneLogLevel)level log:log_msg];
        }
    }
    
}

你可能感兴趣的:(IOS,性能优化,iOS,内存泄漏,instruments,autorelease,混合开发,混编)