2012-02-24 46 views
3

以下兩段代碼可以在優化級別爲-o0時正常工作。 但是,當優化級別是-o0以外的任何其他優化級別時,第一個代碼在某個點崩潰,但秒不會崩潰。你能解釋爲什麼嗎?在iOS中的-o0以外的任何優化級別發生崩潰當優化級別爲-o0時,以下兩段代碼可以正常工作

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; 

編輯: 順便說,這個代碼是在一個內聯函數。如果函數未內聯,即使進行優化,也不會崩潰。

+0

爲什麼不使用調試器並找出自己? :-) – 2012-02-24 13:36:29

+0

我做了 - 沒有發現問題 – 2012-02-24 13:38:29

+3

1和2都打破了嚴格的別名規則。編譯器可以並且會生成崩潰代碼,並生成不會崩潰的代碼。關於這個真的沒什麼可說的。 http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule – 2012-02-24 13:45:40

回答

4

這裏的代碼實際上一次產生幾個問題。首先,如前所述,代碼違反了別名規則,因此每個標準的結果都是不確定的。因此,嚴格來說,編譯器可以在優化時做很多事情(當上面提到的代碼被內聯時,這實際上就是你的情況)。

其次(我相信這是這裏的實際問題) - 鑄造char *爲int *將增加假設的指針對齊。根據你的平臺ABI,char可以是1字節對齊的,但是int - 至少4(double是8字節對齊,btw)。系統可以容忍未對齊的負載,但並不總是如此。在arm/darwin上,它可以容忍4個字節的未對齊的加載,但不能是8.後一種情況可能發生在編譯器決定合併兩個連續的加載/存儲到1之後。因爲碰撞指針編譯器的實際對齊可能推斷出一切都是適合對齊並生成這種8字節的負載。

所以,總之 - 修正你的代碼:)在這種特殊情況下,memcpy/memmove將幫助你。

+0

我想要memcpy,希望它會做的竅門。謝謝你的好解釋:) – 2012-02-25 13:42:39

+0

優秀的解釋。榮譽 – braden 2014-08-01 22:13:47