2006/01/01

[comp] script-aliasing

某一版的 GCC 編譯參數有 void ** 型別的函式會有

dereferencing type-punned pointer will break strict-aliasing rules

這樣的警告訊息.

我是出了名的龜毛, 無法接受在編譯的過程有任何警告. 所以我找出了這個警告的說明. 在 GCC 的臭蟲文件中提到了 script-aliasing 的問題, 但是我遭遇到的問題在文件中並沒有詳細的說明. 不過由此文件連結出去的一封信Aliasing, pointer casts and gcc 3.3解釋了這個問題.
這樣的問題可以算是設計不佳, 因為易造成程式撰寫的錯誤; 而警告訊息是為了提醒程式設計師 cast 時要小心.

題外話是 script-aliasing. 臭蟲文件和該封信中舉出了 script-aliasing 可能會發生錯誤的幾種情況.

1. 非正規的型別轉換
#include 

int main()
{
short a[2];

a[0]=0x1111;
a[1]=0x1111;

*(int *)a = 0x22222222; /* violation of aliasing rules */

printf("%x %x\n", a[0], a[1]);
return 0;
}

解決方式:
#include 

int main()
{
union
{
short a[2];
int i;
} u;

u.a[0]=0x1111;
u.a[1]=0x1111;

u.i = 0x22222222;

printf("%x %x\n", u.a[0], u.a[1]);
return 0;
}

2. 不同平台 alignment 的方式不一樣
    char* data;
struct foo_header *tmp, header;

tmp = data + offset;
memcpy(&header, tmp, sizeof(header));

解決方式:
    char* data;
struct foo_header header;

memcpy(&header, data + offset, sizeof(header));

不同版本, 不同參數的 GCC 處理 script-aliasing 的方式都不太一樣, 得到的結果不一樣, 警告與否的情形也不一樣. 我目前用的版本, -O2 -Wall 時會自動加上 -fstrict-aliasing 參數, 會警告 void ** 的情形, 但是對於上述兩個問題並沒有警告. 若想關掉 void ** 的警告加上 -fno-strict-aliasing 即可.