Desgard/iOS-Source-Probe

纯属问个问题 ^ ^

ifelseboyxx opened this issue · 3 comments

看了你这篇 《weak 弱引用的实现方式》 文章 ,里面提到 :

“单步运行,发现会跳入 NSObject.mm 中的 objc_initWeak() 这个方法。在进行编译过程前,clang 其实对 __weak 做了转换,将声明方式做出了如下调整。”

我想问下 你是怎么知道 调用 objc_initWeak 这个函数的? 我自己尝试着 clang, 转换的代码如下:

//转换前

{
            NSObject *obj = [[NSObject alloc] init];
            __weak id obj1 = obj;
        }


//转换后

{
            NSObject *obj = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
            __attribute__((objc_ownership(weak))) id obj1 = obj;
        }

然后 objc_ownership() 又是啥? 我在 runtime 源码里木有搜到...

原文表述确实有些问题,不能说是 Clang 对于代码的转换。感谢提出。

在 Clang 的官方文档中有以下描述:

If value is a null pointer or the object to which it points has begun deallocation, object is zero-initialized. Otherwise, object is registered as a __weak object pointing to value. Equivalent to the following code:

id objc_initWeak(id *object, id value) {
    *addr = 0;
    if (!val) return nil;
    return objc_storeWeak(object, value);
}

objc_initWeak 作为 __weak 对象的初始化入口,也是 __weak 对象生命周期的第一过程。严格意义上来说只能是 Clang 对于 __weak 对象初始化的动作,说转换确实有些不太恰当。

objc_ownership 这个方法之前在 RAC 的源码中看见过,是 @weakify@strongify 宏展开后调用的方法。没有看到过它的实现,但是从行为上来看应该是用来描述两个对象间的持有关系(从 Ownership 这个命名也能看出来..😂)。

最后还是多谢勘误。

clang -rewrite-objc 这个操作转换的代码和实际上编译出来的结果是有出入的(之前我在调试的时候有个很明显的例子,但是我现在忘了🤤),单步调试就可以发现会进入 objc_initWeak 函数。

__attribute__((objc_ownership(weak))) 就是 __weak 预处理后的结果,当然还会有 __strong 的那些,同样的道理。

楼上所有的应该是Block的内存布局吧。block_impl结构体内的函数指针是FuncPtr *fn。但是查看clang关于block的描述,其实应该是void (*invoke)(void *, ...);具体见这里