__block NSObject * obj和块运行时的混乱

工藤CC

clang -rewrite-objc Block.m用来生成的C ++代码Block.m

中的代码在Block.mARC下:

void func() {
    __block NSObject *obj = [[NSObject alloc] init];
    void (^blk)(void) = ^() {
        obj = nil;
    };
}

我相信,当块被复制并移至堆时,堆中的块将保留obj但是在深入研究块运行时的源代码之后,我得到了相反的结果。

生成的c ++代码:

static void __Block_byref_id_object_copy_131(void *dst, void *src) {
 _Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);
}
static void __Block_byref_id_object_dispose_131(void *src) {
 _Block_object_dispose(*(void * *) ((char*)src + 40), 131);
}

struct __Block_byref_obj_0 {
  void *__isa;
__Block_byref_obj_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 NSObject *obj;
};

struct __func_block_impl_0 {
  struct __block_impl impl;
  struct __func_block_desc_0* Desc;
  __Block_byref_obj_0 *obj; // by ref
  __func_block_impl_0(void *fp, struct __func_block_desc_0 *desc, __Block_byref_obj_0 *_obj, int flags=0) : obj(_obj->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __func_block_func_0(struct __func_block_impl_0 *__cself) {
  __Block_byref_obj_0 *obj = __cself->obj; // bound by ref

        (obj->__forwarding->obj) = __null;
    }
static void __func_block_copy_0(struct __func_block_impl_0*dst, struct __func_block_impl_0*src) {_Block_object_assign((void*)&dst->obj, (void*)src->obj, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __func_block_dispose_0(struct __func_block_impl_0*src) {_Block_object_dispose((void*)src->obj, 8/*BLOCK_FIELD_IS_BYREF*/);}

static struct __func_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __func_block_impl_0*, struct __func_block_impl_0*);
  void (*dispose)(struct __func_block_impl_0*);
} __func_block_desc_0_DATA = { 0, sizeof(struct __func_block_impl_0), __func_block_copy_0, __func_block_dispose_0};
void func() {
    __attribute__((__blocks__(byref))) __Block_byref_obj_0 obj = {(void*)0,(__Block_byref_obj_0 *)&obj, 33554432, sizeof(__Block_byref_obj_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"))};
    void (*blk)(void) = ((void (*)())&__func_block_impl_0((void *)__func_block_func_0, &__func_block_desc_0_DATA, (__Block_byref_obj_0 *)&obj, 570425344));
}

注意:33554432isBLOCK_HAS_COPY_DISPOSE570425344is BLOCK_HAS_COPY_DISPOSE|BLOCK_HAS_DESCRIPTOR

复制block时,__func_block_copy_0将调用来处理捕获的变量,在这种情况下,它复制(__Block_byref_obj_0)obj,将obj-> forwarding更改为副本__Block_byref_obj_0等等,所有这些操作都在中进行_Block_object_assign((void*)&dst->obj, (void*)src->obj, 8/*BLOCK_FIELD_IS_BYREF*/);

的源代码_Block_object_assign

void _Block_object_assign(void *destAddr, const void *object, const int flags) {
    //printf("_Block_object_assign(*%p, %p, %x)\n", destAddr, object, flags);
    if ((flags & BLOCK_BYREF_CALLER) == BLOCK_BYREF_CALLER) {
        if ((flags & BLOCK_FIELD_IS_WEAK) == BLOCK_FIELD_IS_WEAK) {
            _Block_assign_weak(object, destAddr);
        }
        else {
            // do *not* retain or *copy* __block variables whatever they are
            _Block_assign((void *)object, destAddr);
        }
    }
    else if ((flags & BLOCK_FIELD_IS_BYREF) == BLOCK_FIELD_IS_BYREF)  {
        // copying a __block reference from the stack Block to the heap
        // flags will indicate if it holds a __weak reference and needs a special isa
        _Block_byref_assign_copy(destAddr, object, flags);
    }
    // (this test must be before next one)
    else if ((flags & BLOCK_FIELD_IS_BLOCK) == BLOCK_FIELD_IS_BLOCK) {
        // copying a Block declared variable from the stack Block to the heap
        _Block_assign(_Block_copy_internal(object, flags), destAddr);
    }
    // (this test must be after previous one)
    else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) {
        //printf("retaining object at %p\n", object);
        _Block_retain_object(object);
        //printf("done retaining object at %p\n", object);
        _Block_assign((void *)object, destAddr);
    }
}


static void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) {
    struct Block_byref **destp = (struct Block_byref **)dest;
    struct Block_byref *src = (struct Block_byref *)arg;

    //printf("_Block_byref_assign_copy called, byref destp %p, src %p, flags %x\n", destp, src, flags);
    //printf("src dump: %s\n", _Block_byref_dump(src));
    if (src->forwarding->flags & BLOCK_IS_GC) {
        ;   // don't need to do any more work
    }
    else if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) {
        //printf("making copy\n");
        // src points to stack
        bool isWeak = ((flags & (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK)) == (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK));
        // if its weak ask for an object (only matters under GC)
        struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak);
        copy->flags = src->flags | _Byref_flag_initial_value; // non-GC one for caller, one for stack
        copy->forwarding = copy; // patch heap copy to point to itself (skip write-barrier)
        src->forwarding = copy;  // patch stack to point to heap copy
        copy->size = src->size;
        if (isWeak) {
            copy->isa = &_NSConcreteWeakBlockVariable;  // mark isa field so it gets weak scanning
        }
        if (src->flags & BLOCK_HAS_COPY_DISPOSE) {
            // Trust copy helper to copy everything of interest
            // If more than one field shows up in a byref block this is wrong XXX
            copy->byref_keep = src->byref_keep;
            copy->byref_destroy = src->byref_destroy;
            (*src->byref_keep)(copy, src);
        }
        else {
            // just bits.  Blast 'em using _Block_memmove in case they're __strong
            _Block_memmove(
                (void *)&copy->byref_keep,
                (void *)&src->byref_keep,
                src->size - sizeof(struct Block_byref_header));
        }
    }
    // already copied to heap
    else if ((src->forwarding->flags & BLOCK_NEEDS_FREE) == BLOCK_NEEDS_FREE) {
        latching_incr_int(&src->forwarding->flags);
    }
    // assign byref data block pointer into new Block
    _Block_assign(src->forwarding, (void **)destp);
}

由于flagBLOCK_FIELD_IS_BYREF,这样的分支去_Block_byref_assign_copy,为的副本这个函数malloc内存__Block_byref_obj_0,并做一些任务,最终它会调用(*src->byref_keep)(copy, src)该点__Block_byref_id_object_copy_131,因为我们可以在这个功能看到的,只有一行代码:

_Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);,131是BLOCK_FIELD_IS_OBJECT|BLOCK_BYREF_CALLER,“(char *)dst + 40”是BLOCK_FIELD_IS_BYREF(copy)的地址,因此它将被调用,_Block_assign((void *)object, destAddr);并且此函数只是执行一个赋值*destAddr = object;,没有保留!!!

我相信obj应该保留,但是源代码似乎没有保留它。我真的很困惑。

我在这里获得了Blocks Runtime的源代码,您可以使用来获取它svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt

更新1:

static void _Block_assign_default(void *value, void **destptr) {
    *destptr = value;
}
static void (*_Block_assign)(void *value, void **destptr) = _Block_assign_default;
CRD

我认为您在分析中缺少的是,您没有看到为ARC插入的呼叫,而是看到了语言级别的分配。

__Block_byref_obj_0您将字段显示obj为:

NSObject *obj;

没有任何明确的所有权限定符。当我运行类似的测试Clang输出时:

NSObject *__strong obj;

包括明确的所有权限定词。

如果您查看程序集级别的代码,将会看到在各个地方都有对ARC内存管理例程的插入的调用。

因此,您看到的简单分配实际上可以编译为一个强大的存储-即释放任何现有引用,保留新引用。当然,这与原始的Objective-C完全相同,您可以将ARC语义“读入”作为语言语义的组成部分。

高温超导

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

__block NSObject * obj和块运行时的混乱

来自分类Dev

[NSObject:AnyObject]!和joinWithSeparator

来自分类Dev

NSObject和Struct之间的区别

来自分类Dev

id <protocol>和NSObject <protocol>之间的区别

来自分类Dev

nsobject vs nsmanagedobject优点和缺点

来自分类Dev

从类“ NSObject”和“ AWSDynamoDBObjectModel”的多重继承

来自分类Dev

从类“ NSObject”和“ AWSDynamoDBObjectModel”的多重继承

来自分类Dev

NSArray和NSObject之间的NSPredicate值匹配

来自分类Dev

NSObject(RACKVOWrapper)rac_observeKeyPath:options:observer:block:EXC_BAD_ACCESS崩溃

来自分类Dev

@interface <文件名>:NSObject和@interface NSObject(文件名)之间的区别是什么?

来自分类Dev

从类NSObject和NSCoder的快速错误多重继承

来自分类Dev

如何使用NSObject映射Web服务键和值对?

来自分类Dev

id <protocol> someObject和NSObject <protocol> * someObject之间的区别

来自分类Dev

如何在Swift中的UIViewController和NSObject之间传递数据

来自分类Dev

如何使用NSObject映射Web服务键和值对?

来自分类Dev

如何使用iOS的NSCoder,NSObject和Swift 3解码Double

来自分类Dev

NSProxy与NSObject

来自分类Dev

使用__block和__weak

来自分类Dev

ARC __block和__weak

来自分类Dev

使用__block和__weak

来自分类Dev

如何匹配来自NSObject数组的两个值?(OBJ C)

来自分类Dev

为什么printf在运行循环中无法打印出NSObject?

来自分类Dev

升级到iOS 7和Xcode 5-UIAccelerator,UIStringDrawing和NSObject存在问题

来自分类Dev

对于子类NSCoding和NSObject的自定义类,未调用Equatable类型的==函数

来自分类Dev

是Swift的String,Array和Dictionary NSObjects吗?为什么结构可以是NSObject?

来自分类Dev

如何在iOS中使用NSUserDafaults保存和检索NSObject类

来自分类Dev

Xcode 6.3中针对NSObject不允许使用hash()和description()

来自分类Dev

更新XCode和Swift后'Set <NSObject>'没有名为'containsObject'的成员

来自分类Dev

在NSObject类中声明和定义的视图控制器类中未显示permeterized方法

Related 相关文章

  1. 1

    __block NSObject * obj和块运行时的混乱

  2. 2

    [NSObject:AnyObject]!和joinWithSeparator

  3. 3

    NSObject和Struct之间的区别

  4. 4

    id <protocol>和NSObject <protocol>之间的区别

  5. 5

    nsobject vs nsmanagedobject优点和缺点

  6. 6

    从类“ NSObject”和“ AWSDynamoDBObjectModel”的多重继承

  7. 7

    从类“ NSObject”和“ AWSDynamoDBObjectModel”的多重继承

  8. 8

    NSArray和NSObject之间的NSPredicate值匹配

  9. 9

    NSObject(RACKVOWrapper)rac_observeKeyPath:options:observer:block:EXC_BAD_ACCESS崩溃

  10. 10

    @interface <文件名>:NSObject和@interface NSObject(文件名)之间的区别是什么?

  11. 11

    从类NSObject和NSCoder的快速错误多重继承

  12. 12

    如何使用NSObject映射Web服务键和值对?

  13. 13

    id <protocol> someObject和NSObject <protocol> * someObject之间的区别

  14. 14

    如何在Swift中的UIViewController和NSObject之间传递数据

  15. 15

    如何使用NSObject映射Web服务键和值对?

  16. 16

    如何使用iOS的NSCoder,NSObject和Swift 3解码Double

  17. 17

    NSProxy与NSObject

  18. 18

    使用__block和__weak

  19. 19

    ARC __block和__weak

  20. 20

    使用__block和__weak

  21. 21

    如何匹配来自NSObject数组的两个值?(OBJ C)

  22. 22

    为什么printf在运行循环中无法打印出NSObject?

  23. 23

    升级到iOS 7和Xcode 5-UIAccelerator,UIStringDrawing和NSObject存在问题

  24. 24

    对于子类NSCoding和NSObject的自定义类,未调用Equatable类型的==函数

  25. 25

    是Swift的String,Array和Dictionary NSObjects吗?为什么结构可以是NSObject?

  26. 26

    如何在iOS中使用NSUserDafaults保存和检索NSObject类

  27. 27

    Xcode 6.3中针对NSObject不允许使用hash()和description()

  28. 28

    更新XCode和Swift后'Set <NSObject>'没有名为'containsObject'的成员

  29. 29

    在NSObject类中声明和定义的视图控制器类中未显示permeterized方法

热门标签

归档