ARC下的内存泄漏

##ARC下的内存泄漏

ARC全称叫 ARC(Automatic Reference Counting)。在编译期间,编译器会判断对象的使用情况,并适当的加上retain和release,使得对象的内存被合理的管理。所以,从本质上说ARC和MRC在本质上是一样的,都是通过引用计数的内存管理方式。ARC 的出现大大节省了程序员手动管理内存的时间成本,But,世上没有完美的事物,我们也不要把任何事想的那么美好,在 ARC 环境下如果不注意的话也会引起内存泄漏。

目前在项目中引入了MLeaksFinder,能比较清晰的找到内存泄漏的位置。

##分析一下内存泄漏的主要原因

####循环引用(Retain Cycle)

什么是引用循环(retain cycle) ​假设我们有两个实例A和B,B是A的一个strong型的property,则B的引用计数是1,当A的需要释放的时候,A则会调用[B release]来释放B,B的引用计数则减为0,释放。

​可如果这时候将B的一个strong型property指向A,则A与B互相为强引用,问题就来了。因为B强引用A,A的引用计数永远不会减为0,当A原本的强引用对象被释放以后,A和B成为了一个相互引用的孤岛,永远不会被释放了,这就会引起内存泄漏。

​在上面的例子中,就是一种非常普遍的引用循环情况,加入如上代码的VC在dismiss或者pop以后,并不会执行dealloc方法,证明内存泄漏了。而引起泄漏的原因就是在作为self的property的block中,使用self指针导致self被block强引用,形成引用循环。

1、Delegate 我们在使用代理设计模式的时候,一定要注意将 delegate 变量声明为 weak 类型,像这样 @property (nonatomic, weak) id<xxxx> delegate; 如使用strong或别的类型修饰的话将会导致循环引用,导致dealloc()不会被调用。从而触发一些意想不到的后果。

2、Block 目前在项目中出现的内存泄漏大部分是因为block的问题。 在 ARC 下,当 block 获取到外部变量时,由于编译器无法预测获取到的变量何时会被突然释放,为了保证程序能够正确运行,让 block 持有获取到的变量,向系统声明:我要用它,你们千万别把它回收了!然而,也正因 block 持有了变量,容易导致变量和 block 的循环引用,造成内存泄露!

    [_sortButton setButtonSpreadPreAction:^BOOL{if (_resultItems.count == 0) {[progressHUD showText:@"xxxx"];return NO;}return YES;}];
复制代码

这个例子的问题就在于在使用 block 的过程中形成了循环引用:self 持有 sortButton;sortButton 持有 block;block 持有 self。三者形成循环引用,内存泄露。

GCD已经一些系统级的API并不会提示循环引用的警告,但通过测试发现,大部分系统提供block也是需要弱引用的__weak typeof(self) weakSelf = self; 项目中除了AFN的第三方组件在调用block时都是需要弱引用的,如MJRefresh。

3、NSTimer ​NSTimer在VC释放前,一定要调用[timer invalidate],不调用的后果就是NSTimer无法释放其target,如果target正好是self,则会导致引用循环。

​这里要补充一点,引用循环不是只能有两个对象,三个四个更多都是可以的,甚至环数也不一定只有一个,所以要养成良好的代码习惯,在NSTimer停用前调用invalidate方法。

关于performSelector:afterDelay的问题

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay
复制代码

我们还是看看官方文档怎么说的。 This method sets up a timer to perform the aSelector message on the current thread’s run loop. The timer is configured to run in the default mode (NSDefaultRunLoopMode). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.

大概意思是系统依靠一个timer来保证延时触发,但是只有在runloop在default mode的时候才会执行成功,否则selector会一直等待run loop切换到default mode。根据我们之前关于timer 的说法,在这里其实调用performSelector:afterDelay:同样会造成系统对target强引用,也即retain住。这样子,如果selector一直无法执行的话(比如runloop不是运行在default model下),这样子同样会造成target一直无法被释放掉,发生内存泄露。怎么解决这个问题呢?其实很简单,我们在适当的时候取消掉该调用就行了,系统提供了接口:

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget
复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391347.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python:校验邮箱格式

# coding:utf-8import redef validateEmail(email):if re.match("^.\\(\\[?)[a-zA-Z0-9\\-\\.]\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", email) ! None:# if re.match("/^\w[a-z0-9]\.[a-z]{2,4}$/", email) ! None:print okreturn okelse:print failret…

cad2019字体_这些是2019年最有效的简历字体

cad2019字体When it comes to crafting the perfect resume to land your dream job, you probably think of just about everything but the font. But font is a key part of your first impression to recruiters and employers.当制作一份完美的简历来实现理想的工作时&…

Go语言实战 : API服务器 (4) 配置文件读取及连接数据库

读取配置文件 1. 主函数中增加配置初始化入口 先导入viper包 import (..."github.com/spf13/pflag""github.com/spf13/viper""log")在 main 函数中增加了 config.Init(*cfg) 调用&#xff0c;用来初始化配置&#xff0c;cfg 变量值从命令行 f…

方差偏差权衡_偏差偏差权衡:快速介绍

方差偏差权衡The bias-variance tradeoff is one of the most important but overlooked and misunderstood topics in ML. So, here we want to cover the topic in a simple and short way as possible.偏差-方差折衷是机器学习中最重要但被忽视和误解的主题之一。 因此&…

win10 uwp 让焦点在点击在页面空白处时回到textbox中

原文:win10 uwp 让焦点在点击在页面空白处时回到textbox中在网上 有一个大神问我这样的问题&#xff1a;在做UWP的项目&#xff0c;怎么能让焦点在点击在页面空白处时回到textbox中&#xff1f; 虽然我的小伙伴认为他这是一个 xy 问题&#xff0c;但是我还是回答他这个问题。 首…

python:当文件中出现特定字符串时执行robot用例

#coding:utf-8 import os import datetime import timedef execute_rpt_db_full_effe_cainiao_city():flag Truewhile flag:# 判断该文件是否存在# os.path.isfile("/home/ytospid/opt/docker/jsc_spider/jsc_spider/log/call_proc.log")# 存在则获取昨天日期字符串…

MySQL分库分表方案

1. MySQL分库分表方案 1.1. 问题&#xff1a;1.2. 回答&#xff1a; 1.2.1. 最好的切分MySQL的方式就是&#xff1a;除非万不得已&#xff0c;否则不要去干它。1.2.2. 你的SQL语句不再是声明式的&#xff08;declarative&#xff09;1.2.3. 你招致了大量的网络延时1.2.4. 你失去…

linux创建sudo用户_Linux终极指南-创建Sudo用户

linux创建sudo用户sudo stands for either "superuser do" or "switch user do", and sudo users can execute commands with root/administrative permissions, even malicious ones. Be careful who you grant sudo permissions to – you are quite lit…

重学TCP协议(1) TCP/IP 网络分层以及TCP协议概述

1. TCP/IP 网络分层 TCP/IP协议模型&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;&#xff0c;包含了一系列构成互联网基础的网络协议&#xff0c;是Internet的核心协议&#xff0c;通过20多年的发展已日渐成熟&#xff0c;并被广泛应用于局域网和…

分节符缩写p_p值的缩写是什么?

分节符缩写pp是概率吗&#xff1f; (Is p for probability?) Technically, p-value stands for probability value, but since all of statistics is all about dealing with probabilistic decision-making, that’s probably the least useful name we could give it.从技术…

Spring-----AOP-----事务

xml文件中&#xff1a; 手动处理事务&#xff1a; 设置数据源 <bean id"dataSource" class"com.mchange.v2.c3p0.ComboPooledDataSource"> <property name"driverClass" value"com.mysql.jdbc.Driver"></property…

[测试题]打地鼠

Description 小明听说打地鼠是一件很好玩的游戏&#xff0c;于是他也开始打地鼠。地鼠只有一只&#xff0c;而且一共有N个洞&#xff0c;编号为1到N排成一排&#xff0c;两边是墙壁&#xff0c;小明当然不可能百分百打到&#xff0c;因为他不知道地鼠在哪个洞。小明只能在白天打…

在PHP服务器上使用JavaScript进行缓慢的Loris攻击[及其预防措施!]

Forget the post for a minute, lets begin with what this title is about! This is a web security-based article which will get into the basics about how HTTP works. Well also look at a simple attack which exploits the way the HTTP protocol works.暂时忘掉这个帖…

三星为什么要卖芯片?手机干不过华为小米,半导体好挣钱!

据外媒DigiTimes报道&#xff0c;三星有意向其他手机厂商出售自家的Exynos芯片以扩大市场份额。知情人士透露&#xff0c;三星出售自家芯片旨在提高硅晶圆工厂的利用率&#xff0c;同时提高它们在全球手机处理器市场的份额&#xff0c;尤其是中端市场。 三星为什么要卖芯片&…

重学TCP协议(2) TCP 报文首部

1. TCP 报文首部 1.1 源端口和目标端口 每个TCP段都包含源端和目的端的端口号&#xff0c;用于寻找发端和收端应用进程。这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接 端口号分类 熟知端口号&#xff08;well-known port&#xff09;已登记的端口&am…

linux:vim中全选复制

全选&#xff08;高亮显示&#xff09;&#xff1a;按esc后&#xff0c;然后ggvG或者ggVG 全部复制&#xff1a;按esc后&#xff0c;然后ggyG 全部删除&#xff1a;按esc后&#xff0c;然后dG 解析&#xff1a; gg&#xff1a;是让光标移到首行&#xff0c;在vim才有效&#xf…

机器学习 预测模型_使用机器学习模型预测心力衰竭的生存时间-第一部分

机器学习 预测模型数据科学 &#xff0c; 机器学习 (Data Science, Machine Learning) 前言 (Preface) Cardiovascular diseases are diseases of the heart and blood vessels and they typically include heart attacks, strokes, and heart failures [1]. According to the …

程序2:word count

本程序改变自&#xff1a;http://blog.csdn.net/zhixi1050/article/details/72718638 语言&#xff1a;C 编译环境&#xff1a;visual studio 2015 运行环境&#xff1a;Win10 做出修改的地方&#xff1a;在原码基础上修改了记录行数的功能&#xff0c;删去了不完整行数的记录&…

重学TCP协议(3) 端口号及MTU、MSS

1. 端口相关的命令 1.1 查看端口是否打开 使用 nc 和 telnet 这两个命令可以非常方便的查看到对方端口是否打开或者网络是否可达。如果对端端口没有打开&#xff0c;使用 telnet 和 nc 命令会出现 “Connection refused” 错误 1.2 查看监听端口的进程 使用 netstat sudo …

Diffie Hellman密钥交换

In short, the Diffie Hellman is a widely used technique for securely sending a symmetric encryption key to another party. Before proceeding, let’s discuss why we’d want to use something like the Diffie Hellman in the first place. When transmitting data o…