3

The following two pieces of code works fine when optimization level is -o0. But, when the optimization level is anything other than -o0, the first code crashes at some point, but the seconds does not crash. could you please explain why?

1.

unsigned char* _pos = ...;

double result;

*((int*)&result) = *((int*)_pos;

2.

unsigned char* _pos = ...;
double result;

int* curPos = (int*)_pos;
int* resultPos = (int*)&result;
*resultPos = *curPos;

EDIT: By the way, this code is in an inlined function. When the function is not inlined, there in no crash even with optimizations.

yuji
  • 16,695
  • 4
  • 63
  • 64
Erik Sapir
  • 23,209
  • 28
  • 81
  • 141
  • Why not use the debugger and find out yourself? :-) – John Parker Feb 24 '12 at 13:36
  • 3
    Both 1 and 2 break strict aliasing rules. The compiler can and will generate code that crashes, and generate code that doesn't crash, at its option. There is really not much more to say about it. http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule – Pascal Cuoq Feb 24 '12 at 13:45
  • Does it crash on all iDevices and Simulator? Some time ago there was a popular crash on devices caused by compiler bug: http://stackoverflow.com/questions/4149960/iphone-app-crashes-only-in-release-mode-on-3g/4681838#4681838 – brigadir Feb 24 '12 at 13:49
  • Is there a way to disable strict aliasing? – Erik Sapir Feb 24 '12 at 14:10
  • I don't understand why script aliasing causes the crash in this situation - the crash happens in the following line: *((int*)&result) = *((int*)_pos; – Erik Sapir Feb 24 '12 at 14:12

1 Answers1

4

The code here actually yields several problems at once. First, as it was said before, the code violates the aliasing rules and thus the result is undefined per standard. So, strictly speaking, compiler can do bunch of stuff while optimizing (this is actually your case when the code mentioned above is inlined).

Second (and I believe this is the actual problem here) - casting char* to int* will increase the assumed alignment of the pointer. According to your platform ABI, char can be 1 byte aligned, but int - at least 4 (double is 8 byte aligned, btw). The system can tolerate the unaligned loads, but not always, e.g. on arm/darwin it can tolerate 4 byte unaligned loads, but not 8. The latter case can happen when compiler would decide to merge two consecutive loads / stored into 1. Since you bumped the actual alignment of the pointer compiler might deduce that everything is suitable aligned and generate such 8 byte loads.

So, in short - fix your code :) In this particular case memcpy / memmove will help you.

Anton Korobeynikov
  • 9,074
  • 25
  • 28