This is a known bug and is has been submitted to bugreporter.apple.com under bug id #16040090
NB: This issue only reproducible on a 64-bit (A7) iOS device. If run in the simulator or on a 32-bit device it works fine.
Please note: This bug seems to be fixed in LLVM 5.1, this is the default compiler for Xcode 5.1 (currently in beta).
I have a method -pointValue
(see below), it works fine when compiled with the optimisation level set to -O0
, but using -Os
(the default for Release builds) the compiler optimises out the line that sets the variable point
. point
is used as the return value so any other method calling this gets random values.
The issue can be fixed by declaring the points
variable as volatile
. However, why does the compiler think it can remove the line setting points
? Is it something to do with how I have written the method?
- (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:
uses malloc() to create a 2 element array that is retuned and then this memory is free
'd by the callee.
As requested, the code for -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;
}
Full source code of the encode categories can be found on GitHub.
Example project
As requested by several commenters I have created a simple test project. However, even after setting all the build settings to match the original project I myself cannot reproduce the issue. The bug only shows up on device.
The only thing I can see different is when the project is run with full optimisation on, LLDB can read some of the variables, and trying to print them to the console I get this:
(CGSize) size = <no location, value may have been optimized out>
This is exactly what I get with my failing project but in that instance passing around one of these "optimised out" variables just gives random data (resulting in massive views being created [or failing to be created]).
Below are screen shots of the example app running with -O0 and -Ofast respectively.
Example app running with -O0 (no optimisations), you can see info on the variables
Example app running with -Ofast (full optimisations), you cannot see info on the variables
Running on device
This is the output when running ton device with optimisations off:
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
This is the output when running on device with full optimisations:
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