別名 (計算)

維基百科,自由的百科全書

別名(Aliasing)是指內存中的一個數據位置可以通過程序中的多個名稱來訪問。通過某一個名稱修改數據,其他別名關聯的值也會改變,這是程式設計師可能不會預期到的。別名的存在使得程式的理解、分析及優化程序變得困難。別名分析可以分析處理程序中有關別名的信息。

例子[編輯]

緩衝區溢出[編輯]

大部份C語言的實現都不會有陣列索引的邊界檢查。因此,可以利用此一漏洞,寫入在陣列範圍外的資料(緩衝區溢出),根據C語言的標準,這是未定義行為,但在大部份沒有陣列索引邊界檢查的C語言中,會出現上述的別名效果,用某一個名稱更改資料,而對應別名的數值隨之變化。

若陣列是在呼叫堆疊中產生,而有變數恰好就在陣列位置的前後,寫入陣列索引範圍外的元素,可能就會改到該變數。例如,假設有二個元素的int陣列(其名稱為arr),後面是一個int變數(名稱是i),若arr[2](陣列的第三個元素)位置和i相同,這二個變數就互為別名。

# include <stdio.h>

int main()
{
 int arr[2] = { 1, 2 };
 int i=10;

 /* Write beyond the end of arr. Undefined behaviour in standard C, will write to i in some implementations. */
 arr[2] = 20;

 printf("element 0: %d \t", arr[0]); // outputs 1
 printf("element 1: %d \t", arr[1]); // outputs 2
 printf("element 2: %d \t", arr[2]); // outputs 20, if aliasing occurred
 printf("i: %d \t\t", i); // might also output 20, not 10, because of aliasing, but the compiler might have i stored in a register and print 10
 /* arr size is still 2. */
 printf("arr size: %d \n", (sizeof(arr) / sizeof(int)));
}

在一些C語言的實現中,有可能會出現上述的結果,因為這些實現會為陣列安排一塊連續的記憶體,而陣列元素就是用陣列位置再位移陣列索引值乘以陣列元素大小,再進行間接定址。C語言沒有邊界檢查,因此陣列的存取可能會超過陣列範圍。上述的別名效果其實屬於未定義行為,有些實現方式會不會讓堆疊中的變數緊鄰陣列,例如,依其處理器的長度有對齊功能等。C語言標準沒有特別說明資料在記憶體中擺放的方式(ISO/IEC 9899:1999, section 6.2.6.1)。

若C語言編輯器在存取陣列範圍以外的位置時,沒有別名效果,這也是可以的。

別名指針[編輯]

另一種程式語言中會出現的別名,是指用不同的變數(例如指標)參考同一個位置的記憶體。例如XOR交換演算法英語XOR swap algorithm,其引數是二個指標,函式會假設二個指標指向不同的位置。若二個指標的位置相同(或互為別名),程式可能會出現錯誤。對於接受指標作為引數的函式來說,這是常見的問題,是否允許二個指標互為別名,需要明確的說明,特別是在會在指標指向記憶區塊,進行複雜處理的函式。

優化時衝突[編輯]

優化編譯器在存在指針時往往對變量做出保守假設。如常量傳播能否使用。代碼重排序(code reordering)也受別名的影響,這可能會改善指令調度或允許更多的循環優化英語loop optimization.

C語言C99標準,提出了嚴格別名規則(strict aliasing rule)見section 6.5, paragraph 7。指出使用不同類型的指針訪問同一內存位置是違規的。編譯器因而可以假定不同類型的指針不會是別名,這可能帶來性能的巨大提升。[1]一些著名項目,如Python 2違反了此規則。[2]Linux內核也解決了類似問題。[3] 使用gcc編譯選項-fno-strict-aliasing可關閉此規則。

C++11規定下述廣義左值類型為嚴格別名規則的例外情形:

  • 對象的動態類型
  • cv量化版本
  • signed或unsigned版本
  • 聚合類型(如struct、class)或union類型,包含此前所指的類型作為它的元素,或非靜態數據成員(包括遞歸嵌套類型)
  • 動態類型的基類型
  • char或unsigned

參見[編輯]

參考文獻[編輯]

  1. ^ Mike Acton. Understanding Strict Aliasing. 2006-06-01 [2017-11-20]. (原始內容存檔於2013-05-08). 
  2. ^ Neil Schemenauer. ANSI strict aliasing and Python. 2003-07-17 [2017-11-20]. (原始內容存檔於2020-06-05). 
  3. ^ Linus Torvalds. Re: Invalid compilation without -fno-strict-aliasing. 2003-02-26 [2017-11-20]. (原始內容存檔於2020-11-12). 
  4. ^ Michael Barr. Software Based Memory Testing. 2012-07-27 [2017-11-20]. (原始內容存檔於2020-11-29). 

外部連結[編輯]