block引发的陷阱
block在项目的开发中使用时非常频繁的,苹果官方也极力推荐使用block。其实,究其本质,block就是指向结构体的指针(可利用运行时机制查看底层生成的c代码)。然而在使用block时会存在很多陷阱(主要是内存泄露),这些都是必须要注意的。接下来举个简单的实例:
假设一个类,拥有两个属性:block和name;
//
// SZBlocTest.h
// block引发的内存泄漏
//
// Created by mac on 14-6-17.
// Copyright (c) 2014年 shunzi. All rights reserved.
// #import <Foundation/Foundation.h> @interface SZBlocTest : NSObject @property (nonatomic, copy) void(^block)(); @property (nonatomic, copy) NSString *name; @end
在这之前,先解释下block为什么使用copy来修饰?其主要原因如下:
在普通情况下,任何block,都是存在于栈中,这也意味着,其生命周期由系统管理,不需要我们手动管理.这就存在一个问题,那就是我们如果使用block保存一段代码块,欢乐的等待被回调的时候,说不定在之前就已经被系统回收了!
那么,如何让block存储到堆中呢?方法就是使用copy来修饰,做一次复制.(如果使用retain的话,只会将其计数器加一,多做一次强引用,但不会重新分配新的内存,所以,依然存在于栈中).
此时,产生第二个问题:如果在block中调用持有它的对象(有点绕,理解下),就会产生循环引用,造成内存泄漏!例如:
//
// SZBlocTest.m
// block引发的内存泄漏
//
// Created by mac on 14-6-17.
// Copyright (c) 2014年 shunzi. All rights reserved.
//
#import "SZBlocTest.h" @implementation SZBlocTest
- (id)init
{
if (self = [super init]) {
self.block = ^{
NSLog(@"%@",_name);
NSLog(@"%@",self->_name);
NSLog(@"%@",self.name);
};
}
return self;
}
@end
以上代码中,block中使用的
15 NSLog(@"%@",_name);
16 NSLog(@"%@",self->_name);
17 NSLog(@"%@",self.name); 都会引发循环引用,其中15与16行,是等同的;为什么会引发循环引用呢?
因为,block存在于堆中,在其代码块中引用的对象都会产生一个強指针.而这时候问题就产生了,因为block本身就被其引用的对象(copy)强指针指向着.这样就造成了双方都无法释放,从而造成了内存泄漏. 解决方案如下:
- (id)init
{
if (self = [super init]) {
__unsafe_unretained SZBlocTest *temp = self;
// __weak SZBlocTest *temp = self;
self.block = ^{
NSLog(@"%@",temp->_name);
NSLog(@"%@",temp.name);
};
}
return self;
}
这时候,很多细心的人就会注意到,第五行的被注释的代码
__weak SZBlocTest *temp = self;
和上面的
__unsafe_unretained SZBlocTest *temp = self;
有什么区别呢?
简单说就是,unsafe,为什么不安全呢?因为当其所修饰的对象释放时,它并不知道,所以,其地址依然存在,不会清为nil,这样第七行代码
temp->_name
是可以访问的(在使用时也应当注意这个细节),而使用weak修饰的话,当其修饰的对象被释放时,temp会被清为nil,这样就会出现nil->_name的情况.这是不允许的.
如果想要了解
__unsafe_unretained和__weak的具体区别的话,可查阅其它资料.
block引发的陷阱的更多相关文章
- ie、firefox、chrome中关于style="display:block" 引发的页面布局错乱的解决办法
ie.firefox.chrome中关于style="display:block" 引发的页面布局错乱的解决办法: table中tr 添加style="display:b ...
- for...else: 一个程序引发的陷阱
python3菜鸟教程有一段关于for循环和else搭配的代码: for n in range(2, 10): for x in range(2, n): if n % x == 0: print(n ...
- 由ASIHttpRequest里的block引发的思考
项目发http请求,现在一般的都是用的第三方开源库,当然发异步请求时我们也会写几个回调函数来进行请求返回时的处理.不过前段时间看一个朋友写的代码,里面很用block简单的实现了回调相关的部分.比如: ...
- Foundation: NSNotificationCenter
一个NSNotificationCenter对象(通知中心)提供了在程序中广播消息的机制,它实质上就是一个通知分发表.这个分发表负责维护为各个通知注册的观察者,并在通知到达时,去查找相应的观察者,将通 ...
- 自然对数e(转)
e表示增长的极限 e=limx→+∞ (1+1/x)^x≍2.71828 假设,一根竹子,第一天是1米,第二天长了1米,然后这根柱子的长度变成了2米.相当于 (1+1/1)^1.上面这个假设,如果仔细 ...
- Python 的上下文管理器是怎么设计的?
花下猫语:最近,我在看 Python 3.10 版本的更新内容时,发现有一个关于上下文管理器的小更新,然后,突然发现上下文管理器的设计 PEP 竟然还没人翻译过!于是,我断断续续花了两周时间,终于把这 ...
- C++动态内存管理与源码剖析
引言 在本篇文章中,我们主要剖析c++中的动态内存管理,包括malloc.new expression.operator new.array new和allocator内存分配方法以及对应的内存释放方 ...
- Java 进阶6 异常处理的陷阱
Java 进阶6 异常处理的陷阱 20131113 异常处理机制是 Java语言的特色之一,尤其是 Java的Checked 异常,更是体现了 Java语言的严谨性:没有完善的错误的代码根本就不会被执 ...
- block的哪些事 --- 学习笔记十
//带有自动变量值的匿名函数 //block 与 C语言函数比只有两点不同,1.没有函数名. 2.带有"^". //类似于方法,如B中的值传给A中,在B中,一. 定义 : 二. 实 ...
随机推荐
- BZOJ1968 [Ahoi2005]COMMON 约数研究
Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input ...
- CSS制作图片水平垂直居中
所谓的图片水平垂直居中就是把图片放在一个容器元素中(容器大于图片尺寸或是指定了大小的容器),并且图片位居此容器正中间(中间是指元素容器的正中间),而图片不是以背景图片(background-image ...
- Spring依赖注入:注解注入总结
更多11 spring 依赖注入 注解 java 注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.S ...
- destroy-method="close"的作用
destroy-method="close"的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用.
- MySQL 高效分页
create PROCEDURE USP_GetByPager( _pageindex int, _pagesize int ) BEGIN )*_pagesize; select * from A ...
- 新浪微博客户端(22)-创建微博Cell
DJStatusCell.h #import <UIKit/UIKit.h> @class DJStatusCellFrame; @interface DJStatusCell : UIT ...
- 一个简单的web服务器
写在前面 新的一年了,新的开始,打算重新看一遍asp.net本质论这本书,再重新认识一下,查漏补缺,认认真真的过一遍. 一个简单的web服务器 首先需要引入命名空间: System.Net,关于网络编 ...
- ls -alrth 及ls 详解
idcdpi 抓包过程中 用了命令 ls - alrth :命令,所以回头重新学习 ls命令 linux ls和 ll 命令 标签: linuxsocketssolarisbash出版扩展 2 ...
- js中查找一个字符是否存在。
<script> var a = 'd'; var re = a.indexOf('d'); ){ alert('存在'); } else { alert('不存在'); } </s ...
- 搜狗2013年校园招聘研发类笔试试卷之C/C++类
今天无聊在网上搜了下今年各大NB IT公司的笔试题,搜到了搜狗的,只有扫描版的试卷没有电子版也没有答案,就拿来做了做,题目非常多,涉及到C/C++.Java.数据结构.Android.IOS.Java ...