Block实现-block存储域

Block转换为Block的结构体类型的自动变量,_block变量转换为_block变量的结构体类型的自动变量,所谓结构体类型的自动变量,即栈上生成的该结构体的实例。我们已经了解了block时oc对象,该block的类为_NSConcereteStackBlock,虽然该类并没有出现以变换源代码中,还有很多类似的类

_NSConcereteStackBlock    对象存储域在栈上

_NSConcereteGlobalBlock     域全局变量一样,设置在程序的数据区域(.data中)

_NSConcereteMallocBlock   设置在malloc函数分配的内存(堆上)块中。

下面我们介绍一下一个应用程序的内存分配

并非不是所有的block都是NSConcereteStackBlock,但是事实并不是这样的,在记述全局变量的地方使用Block语法时,生成的block为_NSConcereteGlobalBlock类对象。

#import <Foundation/Foundation.h>
void(^blk)(void)=^{printf("Block");};
int main() {
    blk();
    return 0;
}

将上面源代码进行转换之后得到结果:

struct __blk_block_impl_0 {
  struct __block_impl impl;
  struct __blk_block_desc_0* Desc;
  __blk_block_impl_0(void *fp, struct __blk_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteGlobalBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

我们可以清晰的看到这里的block是全局变量,因为在全局变量的地方不能够使用局部变量,由此可以得知此结构体实例不依赖任何执行时候的状态,所以整个程序只需要一个实例,即使在函数内而不是记述广域变量的地方使用block语法时,之遥block不截获自动变量,就可以将block用结构体设置在程序的数据区域。

在出现一下两种方式的时候,block是_NSConcereteGlobalBlock 类对象

1 记述全局变量的地方使用block语法

2 block语法的表达式中不使用应截获的自动变量的时候。

除此之外的block都要配置在栈上。那么现在问题就来了,我们什么时候使用_NSConcereteMallocBlock,总不能不用,这正是为了解决下面两个问题,

1 Block超出变量作用域但是却可存在。

2 _block变量用结构体成员变量_fowarding存在的原因。

我们需要了解,配置在全局变量上的block在变量作用域外也可以安全的访问,但是配置在栈上的,如果其所属的变量作用域结束,该block就被遗弃,所以Blocks提供了将栈上的block复制到堆上,这样即使block语法记述的变量作用域结束,堆上的block还可以继续存在。

_block变量存储域

需要注意的是,将栈上的_block变量用结构体实例在_block变量从栈上复制到堆上的时候,会将成员变量的_forwarding的值替换为复制目标的堆上的_block变量的结构体实例的地址。

时间: 2024-10-10 10:59:10

Block实现-block存储域的相关文章

Block存储域探析

接<Block截获自动变量实现与__block修饰符内部实现>我们继续探讨Block 留下的问题 1,__Block_byref_i_0 *__forwarding;这个指向自身的指针是什么鬼,有什么作用,什么时候用? 2,Desc_0结构体中多出来的void (*copy) void (*dispose)这两个方法有什么作用,什么时候用? Block 和 __block变量的实质 名称 实质 Block 栈上Block的结构体实例 __block变量 栈上__block变量的结构体实例 Bl

Block存储域

第一.在OC中允许block改写值的变量有三种: 静态变量 全局变量 静态全局变量 code示例如下所示: int global_val=1; staticint static_global_val=2; int main(int argc,const char * argv[]) { @autoreleasepool { static int static_val=3; void (^blk)(void)=^{ global_val *=2; static_global_val+=3; sta

block 解析 - block变量

block变量 上一篇 讲的是block静态变量的特性,这里我们来看一下_block变量.引用官方: You can specify that an imported variable be mutable—that is, read-write— by applying the __block storage type modifier. __blockstorage is similar to, but mutually exclusive of, the register, auto, a

静态block/static block添加至产品描述页的tab方法

magento 产品描述页新增一个tab,调用静态block/static block 内容的方法: 1. 在管理后台的 cms-->static block 新增一个 静态block, 注意创建的 identifier 名称, 这里我假设创建了一个identifier为 shipping 的静态block 2. 创建模型文件:在自己的模版目录的template文件夹里面,新创建一个文件夹为 myblock,在里面新建一个phtml类型的文件,比如 shipping.phtml 3. 打开shi

Initialization failed for block pool Block pool(转载)

2014-06-18 20:34:59,622 FATAL org.apache.hadoop.hdfs.server.datanode.DataNode: Initialization failed for block pool Block pool <registering> (Datanode Uuid unassigned) service to localhost/127.0.0.1:9000java.io.IOException: Incompatible clusterIDs i

js读写Cookie问题(Cookie存储时长、Cookie存储域)汇总

在采集网站用户行为数据/使用js对用户行为做交互时,经常会使用到Cookie,了解Js Cookie的读写,以及一些细节,非常重要.   什么是Cookie 所谓Cookie,只是一条极为短小的信息,它被浏览器自动地放置在访问用户的电脑硬盘中. 例如:C:\Users\[user]\AppData\Roaming\Microsoft\Windows\Cookies 如上图所示,打开的一个文件里面,标示了一个域下多个Cookie的信息. 检测/判断浏览器是否支持Cookie 在绝大多数浏览器中,可

Lucene——Field.Store(存储域选项)及Field.Index(索引选项)

Field.Store.YES或者NO(存储域选项) 设置为YES表示或把这个域中的内容完全存储到文件中,方便进行文本的还原 设置为NO表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原(doc.get) Field.Index(索引选项) Index.ANALYZED:进行分词和索引,适用于标题.内容等 Index.NOT_ANALYZED:进行索引,但是不进行分词,如果身份证号.姓名.ID等,适用于精确搜索 Index.ANALYZED_NOT_NORMS:进行分词但是不

Block实现-block的实质

Block的实质: #import <Foundation/Foundation.h> int main() { void(^blk)(void)=^{printf("Block");}; blk(); return 0; } 使用clang将该block转换. clang -rewrite-objc 源代码文件 转换后形成的block文件是: struct __block_impl { void *isa; int Flags; int Reserved; void *F

IOS使用Block —— 3 Block的两个注意点

首先普及一下内存存储区域知识: 内存分为五大区域:堆.栈.全局区.文字常量区.代码区 堆存放:由new.alloc分配的内存块,由程序员控制释放     p1 = (char *)malloc(10); 栈存放:存放函数参数.局部变量,在不需要的时候由编译器自动清除的变量存储区.   int b;   char s[] = “abc”;   char*p2; 全局区(静态):全局变量和静态变量存储放在一块的,程序结束后由系统释放 文字常量区:常量字符串放在这里,程序结束系统释放 代码区:存放函数