我们在前一章介绍了block的用法,而正确使用block必须要求正确理解block的内存管理问题。这一章,我们只陈述结果而不追寻原因,我们将在下一章深入其原因。

一、block放在哪里

我们针对不同情况来讨论block的存放位置:

1.栈和堆

以下情况中的block位于堆中:

void foo()
{
__block int i = ;
int j = ;
void (^blk)(void);
void (^blkInHeap)(void);
blk = ^{ printf("%d, %d\n", i, j);};//blk在栈里
blkInHeap = Block_copy(blk);//blkInHeap在堆里
} - (void)fooBar
{
_oi = ;
OBJ1* oj = self;
void (^oblk)(void) = ^{ printf("%d\n", oj.oi);};
void (^oblkInHeap)(void) = [oblk copy];//oblkInHeap在堆中
}

2.全局区

以下情况中的block位于全局区:

static int(^maxIntBlock)(int, int) = ^(int a, int b){return a>b?a:b;};
- (void)fooBar
{
int(^maxIntBlockCopied)(int, int) =[maxIntBlock copy];
} void foo()
{
int(^maxIntBlockCopied)(int, int) = Block_copy(maxIntBlock);
}

需要注意的是,这里复制过后的block依旧位于全局区,实际上,复制操作是直接返回了原block对象。

二、block引用的变量在哪里

1.全局区

全局区的变量存储位置与block无关:

static int gVar = ;
//__block static int gMVar = 1; void foo()
{
static int stackVar = ;
// __block static int stackMVar = 0;
}

注意,static变量是不允许添加__block标记的

2.堆栈

此时,你可能会问,当函数foo返回后,栈上的j已经回收,那么blkInHeap怎么能继续使用它?这是因为没有__block标记的变量,会被当做实参传入block的底层实现函数中,当block中的代码被执行时,j已经不是原来的j了,所谓物是人非就是这样吧~

另外,如果使用到变量j的所有block都没有被复制至heap,那么这个变量j也不会被复制至heap。

因此,即使将j++这一句放到blk()这句之前,这段代码执行后,控制台打印结果也是:1024, 1。而不是1024, 2

三、其他特性

1.复制的行为

对block调用复制,有以下几种情况:

1.对全局区的block调用copy,会返回原指针,并且这期间不处理任何东西(至少目前的内部实现是这样);

2.对栈上的block调用copy,每次会返回新复制到堆上的block的指针,同时,所有__block变量都会被复制至堆一份(多次拷贝,只会生成一份)。

3.对已经位于heap上的block,再次调用copy,只会增加block的引用计数。

为什么我们不讨论retian的行为?原因是并没有Block_retain()这样的函数,而且objc里面的retain消息发送给block对象后,其内部实现是什么都不做。

2.objc类中的block复制

objc类实例方法中的block如果被复制至heap,那么当前实例会被增加引用计数,当这个block被释放时,此实例会被减少引用计数。

但如果这个block没有使用当前实例的任何成员,那么当前实例不会被增加引用计数。这也是很自然的道理,我既然没有用到这个instance的任何东西,那么我干嘛要retian它?

我们要注意的一点是,我看到网上有很多人说block引起了实例与block之间的循环引用(retain-cycle),并且给出解决方案:不直接使用self而先将self赋值给一个临时变量,然后再使用这个临时变量。但是,大家注意,我们一定要为这个临时变量增加__block标记(多谢第三篇文章回帖网友的提醒)。

Block介绍(二)内存管理与其他特性的更多相关文章

  1. 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件

    本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用:根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制. 本 ...

  2. iOS之Block总结以及内存管理

    block定义 struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(v ...

  3. Android笔记--Bitmap(二)内存管理

    Bitmap(二) 内存管理 1.使用内存缓存保证流畅性 这种使用方式在ListView等这种滚动条的展示方式中使用最为广泛, 使用内存缓存 内存缓存位图可以提供最快的展示.但代价就是占用一定的内存空 ...

  4. iOS中Block介绍(二)内存管理与其他特性

    我们在前一章介绍了block的用法,而正确使用block必须要求正确理解block的内存管理问题.这一章,我们只陈述结果而不追寻原因,我们将在下一章深入其原因. 一.block放在哪里 我们针对不同情 ...

  5. Block(二)内存管理与其他特性

    一.block放在哪里 我们针对不同情况来讨论block的存放位置: 1.栈和堆 以下情况中的block位于堆中: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  6. Block(二)内存管理与其他特性-b

    一.block放在哪里 我们针对不同情况来讨论block的存放位置: 1.栈和堆 以下情况中的block位于堆中: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  7. 全面介绍Windows内存管理机制及C++内存分配实例

    转自:http://blog.csdn.net/yeming81/article/details/2046193 本文基本上是windows via c/c++上的内容,笔记做得不错.. 本文背景: ...

  8. Spark(二): 内存管理

    Spark 作为一个以擅长内存计算为优势的计算引擎,内存管理方案是其非常重要的模块: Spark的内存可以大体归为两类:execution和storage,前者包括shuffles.joins.sor ...

  9. JVM介绍&自动内存管理机制

    1.介绍JVM(Java Virtual Machine,Java虚拟机) JVM是Java Virtual Machine的缩写,通常成为java虚拟机,作为Java可以进行一次编写,到处执行(Wr ...

随机推荐

  1. MSTest不支持参数化测试的解决方案

    之前的项目中做单元测试一直用的是NUnit,这次做新项目,负责人要求统一用MsTest,理由是MsTest是Visual Studio内置的.用就用吧,我没什么意见.不过用了两天,我就发现一个大问题: ...

  2. Spring 数据源配置二:多数据源

    通过上一节  Spring 数据源配置一: 单一数据源  我们了解单一数据源的配置, 这里我们继续多个数据源的配置 如下(applicationContent.xml 内容) 一:  Spring   ...

  3. [转载]MongoDB开发学习(2)索引的基本操作

    索引能够极大的提高查询的效率.在数据库中简历索引必不可少. 在MongoDB中可以很轻松的创建索引. 默认索引_id_ 开启MongoDB服务器,创建数据库cnblogs,创建集合Users .(关于 ...

  4. Burp Suite Walkthrough(中文版)

    Burp Suite是Web应用程序测试的最佳工具之一,其多种功能可以帮我们执行各种任务.请求的拦截和修改,扫描web应用程序漏洞,以暴力破解登陆表单,执行会话令牌等多种的随机性检查.本文将做一个Bu ...

  5. apt-get用法

    转自apt-get语法- - 对于debian来说,安装软件大多都是通过apt-get来实现的. 1.apt-get update 更新软件包信息库.在Debian中,软件包是通过一个数据库来管理的, ...

  6. 0xc0000428 winload.exe无法验证其数字签名的解决方法

    只要把windows/system32/boot中的winload.exe复制到windows/system32中替换即可!! 只有启动画面会有变化,可以使用魔方等软件进行修复,恢复到之前的样子

  7. 汇编语言第二版 程序在dos中执行情况.P86-87

    假设程序要被dos系统加载到sa:0000的内存中,在这个地址的内存开始会有256个字节的PSP程序,用于加载程序和dos系统的通信.ds中的地址为sa. 真正的程序会在这256个字节之后.所以真正程 ...

  8. 简单讨论数据类型(byte)强制转化后的数值变化规律

    package com.wangzhu.datatype; /** * Java基本数据类型练习 * * @ClassName: DataTypes * @Description: TODO * @a ...

  9. [jobdu]扑克牌顺子

    一开始看到题还以为要DFS还是BFS,后来发现完全不用.排个序,然后看看大小王能不能弥补缺口就行,但后来又发现还要排除有相同大小牌的情况. #include <iostream> #inc ...

  10. SPRING IN ACTION 第4版笔记-第八章Advanced Spring MVC-001- 配置SpringFlow(flow-executor、flow-registry、FlowHandlerMapping、FlowHandlerAdapter)

    一. 1.Wiring a flow executor <flow:flow-executor id="flowExecutor" /> Although the fl ...