当前位置: 首页 > article >正文

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

背景

  通过在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<IZoneTraceCb> 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];
        }
    }
    
}

http://www.kler.cn/a/147967.html

相关文章:

  • 深度学习和图像处理
  • 基于RK3568J多网口电力可信物联网关解决方案
  • 开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-tool usage入门-Qwen-Agent深入学习(四)
  • 远离生成式AI大乱斗,SAS公司揭示亚太区千亿AI市场蓝图
  • 搭建Python2和Python3虚拟环境
  • Springboot 日志处理(非常详细)
  • 利用python对数据进行季节性和趋势拆解
  • bitnami Docker 安装ELK
  • web:[ZJCTF 2019]NiZhuanSiWei1
  • 蚁剑低版本反制
  • 带记忆的超级GPT智能体,能做饭、煮咖啡、整理家务!
  • 未来不远!人工智能赛道,未来不远科技正在跑出加速度
  • DM8误删除操作恢复方案
  • UML建模图文详解教程01——Enterprise Architect的安装与使用
  • 电脑开机过程中,程序的启动的顺序是怎么样的?
  • GZ031 应用软件系统开发赛题第4套
  • 网络运维与网络安全 学习笔记2023.11.28
  • QT中样式表常见属性与颜色的设置与应用
  • 优雅使用docker-compose部署Skywalking
  • 前端页面带值跳转
  • re:Invent 2023 开发者指南来了!@开发者们,Let‘s 构!
  • 案例026:基于微信的原创音乐小程序的设计与实现
  • 【电路笔记】-电阻器颜色代码与阻值计算
  • 在MySQL中将一个表切换到另一个表并启用分区
  • 随笔美文2
  • 16、单例bean的优势