objective-c - 当我在 OC 中使用强指针引用 block 中的弱指针时,它会变成悬空指针吗?

标签 objective-c objective-c-blocks

正如问题所描述的, block 中的wSelf会变得悬空吗?

1    void bindDefaultCallbacks {
2   __weak typeof(self) wSelf = self;
2   [sessionManager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
4            __strong typeof(self) sSelf = wSelf;
5            if (!sSelf) {
6                return;
7            }
8
9            // will wSelf here become dangling ?
10           APIRequest *apiRequest = [wSelf apiRequestForTask:dataTask];
11           NSURLResponse *response = dataTask.response;
12           apiRequest.urlResponse = response;
13        }];
14 }

崩溃信息:

Exception Codes: SEGV_ACCERR at 0x0000000000000010
Exception Type: SIGSEGV

0 XXX ___73-[XXXX bindDefaultCallbacks:withSessionManager:]_block_invoke.251 (in XXX) 420
1 XXX -[AFURLSessionManager URLSession:dataTask:didReceiveData:] (in XXX) (AFURLSessionManager.m:1156) 20

最佳答案

在第 10 行,您将不会有悬空指针。 ARC 将确保指针有效或为零(Chris 的引用文献解释了这一点)。然而,在第 10 行,指针可能为零。无法保证 sSelf 引用将在第 5 行之后继续,因为此后不再使用它。

也没有 promise wSelf 在第 10 行为零。两种情况都是有效的。仅 promise 它是指向 self 的有效指针或 nil。

这条规则的正式定义来自Clang documentation discussion of Precise Lifetime Semantics (强调):

In general, ARC maintains an invariant that a retainable object pointer held in a __strong object will be retained for the full formal lifetime of the object. Objects subject to this invariant have precise lifetime semantics.

By default, local variables of automatic storage duration do not have precise lifetime semantics. Such objects are simply strong references which hold values of retainable object pointer type, and these values are still fully subject to the optimizations on values under local control.

A local variable of retainable object owner type and automatic storage duration may be annotated with the objc_precise_lifetime attribute to indicate that it should be considered to be an object with precise lifetime semantics.

请参阅“对象活跃度”周围的部分以获取更多说明。

虽然这个特定的代码很难失败(在第 5 行和第 10 行之间的一个非常短暂的窗口期间,需要在不同的线程上释放该对象),但这种一般情况实际上是一个相当常见的原因错误。在调试版本中,强引用往往会一直存在,直到其范围结束,但在优化版本中,它们往往会尽快发布。因此,在开发过程中正常工作的代码在交付时可能会失败(如果您使用原始指针指向您认为正在保留的对象,甚至会崩溃)。

这个错误非常常见,以至于 UIKit 中有注释可以帮助防止它。如果您查看 UIColor.h,您会看到 CGColor 属性是这样定义的:

@property(nonatomic,readonly) CGColorRef CGColor;
- (CGColorRef)CGColor NS_RETURNS_INNER_POINTER CF_RETURNS_NOT_RETAINED;

NS_RETURNS_INNER_POINTER是对 ARC 的警告,表明该指针应导致对象的生命周期延长,即使通常 ARC 不需要它。 (这是 early days of ARC 中崩溃的一个令人讨厌且常见的原因。)

关于objective-c - 当我在 OC 中使用强指针引用 block 中的弱指针时,它会变成悬空指针吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73051123/

相关文章:

ios - 使用__block变量阻止泄漏

iphone - 阻止在 IOS 7 中不被调用和不动画

iphone - self.myIvar 和 myIvar 之间有什么不同?

ios - 如何从 ALAsset 对象获取全景图

objective-c - 覆盖类类别中的属性 setter

objective-c - 在传递给构造函数的 block 中引用 self

ios - 如何处理并发执行的大量数据(NSOperationQueue 或 Blocks)

ios - 使用APNS发送远程推送通知的送达报告-IOS

ios - 将 segue 添加到分割 View Controller

ios - 在 iOS 中,如何仅在 Parse.com 的所有查找/保存操作完成后才执行某些代码?