Block的详细介绍
关于block
的介绍
==
ios
中的内存空间分级==
- 栈区
- 存放函数参数值、局部变量、函数返回地址等,函数跳转跳转时现场保护(寄存器),这些系统都会帮我们自动实现,无需我们干预。 所以大量的局部变量,深递归,函数循环调用都可能耗尽栈内存而造成程序崩溃 。我们每次调用函数,都会执行压栈操作(在XCode的左侧面板会看到一堆的函数调用栈)。
- 特点是存取效率高,存取结构连续,但是空间很小,有系统自行分配以及管理栈的地址空间。
- 一种先进后出,压栈出栈更像是一个容器。
- 堆区
- 平时涉及到内存管理基本上出自于这个区域。由malloc、alloc、copy(深复制)、new等方法触发的效果就是在堆区进行内存分配。
- 堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
- 数据呈现一般是树状的,类似链表式
- 常量区
- 存放常量,由系统释放以及分配。
- 静态区
- 该区域其实细分为数据区以及
BSS
区(BSS
是英文Block Started by Symbol
的简称。BSS
段属于静态内存分配。BSS
节不包含任何数据,只是简单的维护开始和结束的地址,以便内存区能在运行时被有效地清零。BSS
节在应用程序的二进制映象文件中并不存在。)。数据区存放已经初始化好的静态变量以及全局变量,而BSS区则存放还没有初始化好的静态变量以及全局变量,由系统负责释放以及分配。 - 是存放开辟过和未开辟过静态变量和全局变量的地方。
- 该区域其实细分为数据区以及
- 文本区
- 放置已经编译成二进制机器语言的代码文本。会依照应用的运行情况而依次调用。类似游戏规则。
==
block
的分级==
- 全局区的
Block
:__NSGlobalBlock__
;- 当我们声明一个
block
时,如果这个block
没有捕获外部的变量,那么这个block
就位于全局区,此时对NSGlobalBlock
的retain、copy、release
操作都无效。
- 当我们声明一个
- 栈区的
Block
:__NSStackBlock__
;- 平时编程的时候很少遇到位于栈区的
block
,为什么呢?因为在ARC环境下,当我们声明并且定义了一个block
,并且没有为Block
添加额外的修饰符(默认是__strong
修饰符),如果该Block
捕获了外部的变量,实质上是有一个从__NSStackBlock__
转变到__NSMallocBlock__
的过程,只不过是系统帮我们完成了copy
操作,将栈区的block
迁移到堆区,延长了Block
的生命周期。对于栈区block
而言,栈block
在当函数退出的时候,该空间就会被回收。什么时候在ARC
的环境下出现__NSStackBlock__
呢?如果我们在声明一个block的时候,使用了__weak
或者__unsafe__unretained
的修饰符,那么系统就不会为我们做copy
的操作,不会将其迁移到堆区。
- 平时编程的时候很少遇到位于栈区的
- 堆区的
Block
:__NSMallocBlock__
;我们需要手动调用
copy
方法才可以将block
迁移到堆区,而在ARC环境下,__strong
修饰的(默认)block
只要捕获了外部变量就会位于堆区,NSMallocBlock
支持retain、release
,会对其引用计数+1或 -1。==
__block
修饰符==
- 应该是考虑到了
block
的特殊性,block
也属于“函数”的范畴,变量进入block
,实际就是已经改变了作用域。在几个作用域之间进行切换时,如果不加上这样的限制,变量的可维护性将大大降低。又比如我想在block
内声明了一个与外部同名的变量,此时是允许呢还是不允许呢?只有加上了这样的限制,这样的情景才能实现。于是栈区变成了红灯区,堆区变成了绿灯区。 - 对于捕获的普通的外部变量,
block
并不能作出修改。我们要改变外部变量的内存地址,也就是使用__block
修饰符将外部变量在栈中指针的内存地址,迁移到堆区中来。 __block
修饰符的根本操作就是改变外部变量的内存地址,并不是简单地使得写操作生效。- 那么什么情况下不需要
__block
作为修饰符。将block
捕获的外部变量使用static
修饰或者将外部变量声明为全局变量,那么block
是可以直接修改该外部变量的,因为全局变量或静态变量在内存中的地址是固定的(存放于静态区),Block
在读取该变量值的时候是直接从其所在内存读出,获取到的是最新值,而不是在定义时copy
的常量。 某些图方便直接用
copy
修饰生命block
。直接拿到一个堆区block
。里面捕获变量的过程中就不需要修饰符来让OS
帮忙拷贝直接可以使用了。但是原理一定要清晰,一个失控的机制远比可控的机制恐怖的多。这里需要警醒。==循环引用的原理==
- 循环引用是因为出现了资源的持有闭环。
OS
的判定机制会认为这个空间仍在使用,所以相关联的三方资源一个都不会释放; __weak
的弱引用替换掉__strong
的时候会打破闭环释放三方资源。但是随之到来的是unsafe
。这是需要注意的地方;
==
block
究竟是个什么东西==
- 由上面种种,我们可以推测出。
block
算是一个另类的函数。是将代码段闭包抽象为一种对象调用的手段。
==多线程下的
block
==
- 存不存在资源抢夺?会出现哪些问题?如果有该怎么避免?
Block的详细介绍的更多相关文章
- 【转载】硬盘MBR详细介绍
原文地址:http://blog.chinaunix.net/uid-15007890-id-106892.html 硬盘MBR详细介绍 硬盘是现在计算机上最常用的存储器之一.我们都知道,计 ...
- ISO14443标准详细介绍
这篇文章从各方面详细介绍了ISO/IEC14443标准.第一部分:物理特性1.范围ISO/IEC14443的这一部分规定了邻近卡(PICC)的物理特性.它应用于在耦合设备附近操作的ID-1型识别卡.I ...
- Xilinx Vivado的使用详细介绍(3):使用IP核
ilinx Vivado的使用详细介绍(3):使用IP核 Author:zhangxianhe IP核(IP Core) Vivado中有很多IP核可以直接使用,例如数学运算(乘法器.除法器.浮点运算 ...
- 【转】JSF中的三大核心组件 UI标签的详细介绍和使用举例
JSF提供了大量的UI标签来简化创建视图.这些UI标签类似于ASP.NET中的服务器组件.使用这些标签,可以通过其value,binding,action,actionListener等属性直接绑定到 ...
- HTML5中<template>标签的详细介绍
HTML5中<template>标签的详细介绍(图文) 这篇文章主要介绍了HTML5中的template标签,是HTML5入门中的重要知识,需要的朋友可以参考 一.HTML5 templa ...
- 详细介绍Redis的几种数据结构以及使用注意事项(转)
原文:详细介绍Redis的几种数据结构以及使用注意事项 1. Overview 1.1 资料 <The Little Redis Book>,最好的入门小册子,可以先于一切文档之前看,免费 ...
- 一.Select 函数详细介绍【转】
转自:http://www.cnblogs.com/hjslovewcl/archive/2011/03/16/2314330.html Select在Socket编程中还是比较重要的,可是对于初学S ...
- kvm详细介绍
KVM详解,太详细太深入了,经典 2016-07-18 19:56:38 分类: 虚拟化 原文地址:KVM详解,太详细太深入了,经典 作者:zzjlzx KVM 介绍(1):简介及安装 http:// ...
- Android自动化测试探索(一)adb详细介绍
adb详细介绍 #1. 基本简介 adb,即Android Debug Bridge,它是Android开发/测试人员不可替代的强大工具 #2. Mac上安装adb 安装brew /usr/bin/r ...
随机推荐
- 《Microsoft Sql server 2008 Internals》读书笔记--第六章Indexes:Internals and Management(1)
<Microsoft Sql server 2008 Internals>索引文件夹: <Microsoft Sql server 2008 Internals>读书笔记--文 ...
- 【Excle数据透视表】如何水平并排显示报表筛选区域的字段
原始效果 目标效果 解决方案 设置数据透视表"在报表区域筛选显示字段"为"水平并排" 步骤 方法① 单击数据透视表任意单元格→数据透视表工具→分析→选项→布局和 ...
- 微博,and java 多线程编程 入门到精通 将cpu 的那个 张振华
http://down.51cto.com/data/2263476 java 多线程编程 入门到精通 将cpu 的那个 张振华 多个用户可以同时用一个 vhost,但是vhost之间是隔离的. ...
- git个人使用总结(命令版)
一.基础命令 快照类操作:add.status.diff.commit.reset.rm.mv 分支类基本操作:branch.checkout.log.stash 分享及更新项目基本操作:pull.p ...
- Python 多线程和单线程本质应用区别
先了解下CPU的简单运行原理: 它运行速度非常快,1s内可以运行成千上万次,一个核心可以把1s切分成成千上万个时间片段,这个核心确实同时只能运行一个任务:但是可以将多个任务交替执行,比如上一个时间片段 ...
- file_put_contents执行返回false,file_put_contents false(linux服务器httpd)
file_put_contents执行返回false,file_put_contents false(linux服务器httpd) 默认下selinux是开启的查看SELinux状态:1./usr/s ...
- php单元测试入门教程phpunit详解
本文档提供了一些phpunit官方教程没有提到的信息,帮助初学者快速了解php单元测试,在phpunit官网提供了详细的中文教程,可选多种格式下载 phpunit官网地址:https://phpuni ...
- mysql 5.7 迁移数据方案
从一台服务器迁移至其他服务器,如何选择最短的停服时间方案 方案一.凌晨3点的全备份+停服后一天的大概一天的增备 1. 拷贝前一天的全备份至新的服务器 rsync -auzrP /Data/dbbak/ ...
- e.target与e.currentTarget对比
复制以下代码,即可查看效果 <!DOCTYPE html> <html> <head lang="en"> <meta charset=& ...
- Hadoop学习笔记——Hadoop经常使用命令
Hadoop下有一些经常使用的命令,通过这些命令能够非常方便操作Hadoop上的文件. 1.查看指定文件夹下的内容 语法: hadoop fs -ls 文件文件夹 2.打开某个已存在的文件 语法: h ...