objective-c - 在 objc ARC 下使用 -Os 过度释放,但不使用 -O0

标签 objective-c automatic-ref-counting llvm

我已经针对以下问题提交了一个雷达 (rdar://12311693, http://openradar.appspot.com/12311693),但我想我也会在这里发帖,看看是否有人能发现我的代码中可能导致的错误崩溃。

以下代码示例在编译器优化打开 (-Os) 的情况下由于过度释放而导致崩溃,但在编译器优化关闭 (-O0) 时不会崩溃。该项目正在使用 Xcode 4.4.1 (4F1003)、Apple LLVM 编译器 4.0 构建

当 num2 被过度释放时,应用程序崩溃。启用 Zombie Objects 以确认是这种情况。

// This crashes under -Os, but not under -O0
NSNumber *num1 = @((float)arc4random() / (float)UINT32_MAX);
NSNumber *num2 = @((float)arc4random() / (float)UINT32_MAX);

NSNumber *foo1 = num1;
NSNumber *foo2 = num2;

for (NSUInteger i=0; i<2; i++) {

    NSLog(@"foo1: %p %@", foo1, foo1);
    NSLog(@"foo2: %p %@", foo2, foo2);

    // swap foo1 and foo2
    foo1 = num2;
    foo2 = num1;
}

最佳答案

编译器错误。感谢您提交。

num1num2 应该保证指向实例的生命周期。我怀疑优化器 [正确] 重用堆栈槽并 [错误] 发出导致问题的释放/保留序列。


回应stackmaster;这是一个编译器错误。 ARC 的全部意义在于将 Objective-C 转换到编译器可以 100% 确定地分析代码以了解保留/释放的位置,这样开发人员就不必这样做了。总的来说,即使面对线程,只要在 MRR 世界中使用该对象的所有代码都表现良好并且开发人员不“逃脱”ARC 控制之外的对象,并且做一些淘气的事。两个很大的假设,但比 MRR 有了巨大的改进。

最后,如果您的代码在优化后无法正常工作(没有编译器错误出现时)那是因为您的代码已损坏。正确编写的优化器不会破坏正确编写的代码

虽然有些编译器的错误是出了名的,但 LLVM 不是其中之一(我不会对 GCC 发表任何声明,因为我已经很多年没有使用它了,但我敢打赌也可以这么说)。 iOS 或 OS X 系统将在每次启动时执行数百万行编译启用优化代码,并且系统运行良好。

所以,不,“优化器已打开”永远不是崩溃的最终解决方案。


正如 Catfish_man 指出的那样,有一些深奥的优化器选项会故意产生技术上不正确的代码。它们不是由 -Os 或其他“标准”优化启用的。它们主要集中在数学运算上,因此通常不会导致崩溃,因为错误会更快地蔓延到计算中。

关于objective-c - 在 objc ARC 下使用 -Os 过度释放,但不使用 -O0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12464074/

相关文章:

ios - 动画字体大小

objective-c - 在此 block 中强烈捕获 self 可能会导致保留循环

c++ - 如何在同一台计算机上同时安装多个版本的 llvm libc++(ubuntu)?

将 llvm .bc 文件转换为人类可读的 .ll 文件

c++ - 带有 clang 的 OpenMP

iphone - 如何声明 NSDecimal 以及如何使用 NSDecimalAdd

iphone - EXC_BAD_ACCESS 当 popViewController

iphone - MKMapView 缩放到 viewDidLoad 上的用户位置?

ios - 带有 ARC 的 cellForRowAtIndexPath 中的内存泄漏

iOS:如何销毁 ARC 中的单例?我是不是该?