这是一个已知错误,已在错误ID #16040090
下提交给bugreporter.apple.comNB:此问题仅在64位(A7)iOS设备上可重现。如果在模拟器或32位设备上运行,它可以正常工作。
请注意:这个错误似乎在LLVM 5.1中得到修复,这是Xcode 5.1的默认编译器(目前处于测试阶段)。
我有一个方法-pointValue
(见下文),在优化级别设置为-O0
的情况下编译时工作正常,但使用-Os
(发布版本的默认值)编译器优化设置变量point
的行。 point
用作返回值,因此调用此方法的任何其他方法都会获得随机值。
可以通过将points
变量声明为volatile
来解决此问题。但是,为什么编译器认为它可以删除行设置points
?这与我编写方法的方式有关吗?
- (CGPoint)pointValue
{
ULongLong encodedPoint = [self unsignedLongLongValue];
ULongLong *values = [self splitEncodedInteger:encodedPoint withShift:SHIFT];
//volatile is required to prevent optimising out
volatile CGPoint point = CGPointMake(values[0], values[1]);
free(values); //clean up
return point;
}
NB: -splitEncodedInteger:withShift:
使用malloc()创建一个被重新调整的2元素数组,然后被调用者调用此内存为free
。
根据要求,-splitEncodedInteger:withShift:
- (ULongLong *)splitEncodedInteger:(ULongLong)encocedInteger withShift:(int)shiftValue
{
ULongLong *splitFloats = malloc(sizeof(ULongLong) * 2);
splitFloats[0] = (encocedInteger >> shiftValue);
splitFloats[1] = encocedInteger - ((encocedInteger >> shiftValue) << shiftValue);
return splitFloats;
}
完整source code个编码类别可以是found on GitHub。
根据几位评论者的要求,我创建了一个simple test project。 但是,即使设置了所有构建设置以匹配原始项目,我自己也无法重现该问题。该错误仅显示 on device 。
我唯一能看到的不同是当项目运行完全优化时,LLDB可以读取一些变量,并尝试将它们打印到控制台我得到了这个:
(CGSize) size = <no location, value may have been optimized out>
这正是我对失败的项目所得到的,但在这种情况下,传递其中一个“优化的”变量只会提供随机数据(导致创建大量视图[或无法创建])。
以下是分别使用-O0和-Ofast运行的示例应用程序的屏幕截图。
使用-O0运行的示例应用程序(无优化),您可以看到有关变量的信息
使用-Ofast(完全优化)运行的示例应用,无法查看有关变量的信息
这是运行ton设备且优化关闭时的输出:
2014-02-10 11:36:00.771 optimisation-bug[461:60b] *** Compiling with no optmisations, the code should work as expected ***
2014-02-10 11:36:00.773 optimisation-bug[461:60b] encodedRect: 50332672
2014-02-10 11:36:00.774 optimisation-bug[461:60b] encodedSize: 45089712
2014-02-10 11:36:00.775 optimisation-bug[461:60b] encodePoint: 2621480
2014-02-10 11:36:05.629 optimisation-bug[461:60b] rect: {{0, 0}, {768, 1024}}
2014-02-10 11:36:06.099 optimisation-bug[461:60b] size: {688, 944}
2014-02-10 11:36:06.101 optimisation-bug[461:60b] point: 40.000000, 40.000000
2014-02-10 11:36:06.103 optimisation-bug[461:60b] DONE
这是在具有完全优化的设备上运行时的输出:
2014-02-10 11:44:53.975 optimisation-bug[471:60b] >>> Compiling with -Os optmisations, the code should *NOT* work as expected <<<
2014-02-10 11:44:53.977 optimisation-bug[471:60b] encodedRect: 50332672
2014-02-10 11:44:53.977 optimisation-bug[471:60b] encodedSize: 45089712
2014-02-10 11:44:53.978 optimisation-bug[471:60b] encodePoint: 2621480
2014-02-10 11:44:58.176 optimisation-bug[471:60b] rect: {{1.3464973428307575e+19, 6174053600}, {1.3464973428307575e+19, 1.2554206452792682e+58}}
2014-02-10 11:44:58.178 optimisation-bug[471:60b] size: {1.3464973428307575e+19, 6174053568}
2014-02-10 11:44:58.180 optimisation-bug[471:60b] point: 13464973428307574784.000000, 6174053568.000000
2014-02-10 11:44:58.182 optimisation-bug[471:60b] DONE
答案 0 :(得分:2)
这个问题似乎是arm64编译器中的一个错误; armv7(s)和x86(模拟器)运行代码没有问题。
- (CGPoint)pointValue
{
ULongLong encodedPoint = [self unsignedLongLongValue];
ULongLong *values = [self splitEncodedInteger:encodedPoint withShift:SHIFT];
//volatile is required to prevent optimising out
/*volatile*/ CGPoint point = CGPointMake(values[0], values[1]);
free(values); //clean up
return point;
}
似乎正在发生的事情是free(values)
行在优化阶段被重新排序,并在CGPointMake(...)
之前运行,导致pointer
返回垃圾值。