news 2026/9/25 6:13:11

iOS内存泄漏的常见情况

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
iOS内存泄漏的常见情况

最近面试了一波,有个内存泄漏的问题现在回顾一下

首先,概念我之前有点不明确吧,面试的时候回答的有点含糊由于朋友内推去面试的也算蒙混过关了~

内存溢出:用户要求系统分配的内存空间超出了系统所能提供的范围,称内存溢出

内存泄露:用户向系统申请内存(new),使用完后没有释放的情况(delete),导致了该块内存不能再被用户使用,也不能被系统调用。我们常说的内存泄露指的是堆泄露

内存越界:使用已申请的内存时,超出了内存的界限。

栈溢出:栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。

ps:典型的,在C语言中,在分配数组时为其分配的长度是1024,但往其中装入超过1024个数据时,由于C语言不会对数组操作进行越界检查,就会造成内存溢出错误。出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量超过1m而导致溢出。

栈溢出解决方法

方法一:用栈把递归转换成非递归

通常,一个函数在调用另一个函数之前,要作如下的事情:a)将实在参数,返回地址等信息传递给被调用函数保存; b)为被调用函数的局部变量分配存储区;c)将控制转移到被调函数的入口. 从被调用函数返回调用函数之前,也要做三件事情:a)保存被调函数的计算结果;b)释放被调函数的数据区;c)依照被调函数保存的返回地址将控制转移到调用函数.所有的这些,不论是变量还是地址,本质上来说都是"数据",都是保存在系统所分配的栈中的. 那么自己就可以写一个栈来存储必要的数据,以减少系统负担。

方法二:使用static对象替代nonstatic局部对象

在递归函数设计中,可以使用static对象替代nonstatic局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销,而且static对象还可以保存递归调用的中间状态,并且可为各个调用层所访问。

方法三:增大堆栈大小值

当创建一个线程的堆栈时,系统将会保留一个链接程序的/STACK开关指明的地址空间区域。但是,当调用CreateThread或_beginthreadex函数时,可以重载原先提交的内存数量。这两个函数都有一个参数,可以用来重载原先提交给堆栈的地址空间的内存数量。如果设定这个参数为0,那么系统将使用/STACK开关指明的已提交的堆栈大小值。后面将假定我们使用默认的堆栈大小值,即1MB的保留区域,每次提交一个页面的内存。

之后,回归主题,再说一下iOS内存泄漏的常见情况

1.声明delegate为strong类型,简而言之,如果父VC持有子VC,并设置子VC的delegate为self(也就是父VC),这样的结果就是子VC也间接持有了父VC,造成循环引用,在Pop子VC的时候不会调用delloc。

2.timer是否持有self,我们一般要执行一个timer的时候会用(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo 这里的aTarget一般是self,这时候就需要注意了,如果在你退出的时候这个timer还在执行的话由于这个timer会持有self,所以delloc也不会调用,这里可以用weakSelf代替self也是没有问题的。

3.最常见的就是block导致的循环引用,由于在重构APP中用到了MVVM架构,使用了大量的信号机制,导致block到处飞(哈哈),解决的最多的就是这种了,解决方法也很简单,就是在block外声明__weak type(self) weakSelf = self,在block中用weakSelf就可以了,还有就是在block中如果使用了成员变量的下划线形式也要改成weakSelf.PropertyName的形式。MVVM中定义了宏对@weakify(self)和@strongify(self)可以理解为__weak type(self) weakSelf = self的简化形式,可以拿来直接使用。

3.图片没释放,instrument调试后,发现没被释放的全是imageIO,差不多就知道了,把读图的方式,从[UIImage imageNamed:@""],改成imageWithContentsOfFile,就可以了。

4.使用GPUImage处理拍照的时候,内存稳定不明增长。是Xcode7.1的问题。。只在debug的时候导致内存崩溃,release的时候并不会造成内存溢出,所以可以不必管它。

5.CoreFoundation对象(C对象) : 只要函数中包含了create\new\copy\retain等关键字, 那么这些方法产生的对象, 就必须在不再使用的时候调用1次CFRelease或者其他release函数

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 6:12:36

用WinHex定位文件首扇区:NTFS簇号到LBA的换算实战

简介:借助WinHex深入磁盘底层,讲解如何定位文件中第一个扇区,适合数据恢复、系统调试与安全分析方向的开发运维人员。内容从MBR主引导记录、分区表解析入手,逐步延伸到FAT32文件系统的DBR、FAT表与根目录计算,最后演示…

作者头像 李华
网站建设 2026/9/25 6:07:35

32位单片机选型指南:STM32与国产芯片的深度对比

不开篇说废话了,直接进入正题。作为一个从8位机一路玩到Cortex-M7、这几年又把国产单片机翻来覆去折腾过的人,我想认真聊聊32位单片机的选型这件事。现在网上聊32位单片机绕不开两个关键词:一个是统治了教科书和毕业设计多年的STM32&#xff…

作者头像 李华
网站建设 2026/9/25 6:05:56

Windows CMD查用户名:环境变量、net user与whoami原理对比

1. 项目概述:一条命令看清你是谁——CMD里查用户名的底层逻辑与实战价值在Windows系统里敲下echo %username%,屏幕上立刻跳出你的登录名——这看起来像一句魔法咒语,简单得让人怀疑它是否真有技术含量。但恰恰是这种“一眼看穿”的能力&#…

作者头像 李华