今天終於稍微了解了 AnyCPU的用意了。特地記錄下來,避免記憶體 reset 的老問題。
Visual Studio.NET 2003
在這個年代之前,並沒有64位元的 CPU(應該說不普及)。此時 Visual Studio 並不提供 CPU 相關的選項。回想一下,這是多麼美好的事。
Visual Studio 2005,2008
也才再過個兩年,64 位元的 CPU 開始在伺服器上普遍了起來。到了2007年前後,連桌上電腦也愈來愈普及。為了面對問題,微軟 Visual Studio 2005 開始有了 AnyCPU 的平台目標選項。
那到底使用 AnyCPU 的 assembly 會如何的被地行呢?此時的決策是非常簡單,而且看來也十分有效:
當 assembly 使用的是 AnyCPU 平台目標時,且
- 執行在 32 位元Windows作業系統時,會以 32 位元的方式執行,IL 會被編譯成 x86 的 native code。
- 執行在 64 位元Windows作業系統時,會以 64 位元的方式執行,IL 會被編譯成 x64 的 native code。
問題
由於目前的64位元電腦 (Windows) 都是32位元相容的,因此一個 assembly 在64位元的電腦只能以 64 位元的方式來執行,恐怕不妙。我常碰到的例子是 Oracle Client。
當我們的存取 Oracle 資料庫的程式以 AnyCPU 編譯後,執行在 64 位元的電腦,會以 64 位元的方式來執行。但如果安裝的 Oracle Client 是32位元的呢?32 位元的 Oracle Client 載入 64 位元的程式,就會拋出 System.BadImageFormatException 例外。
Visual Studio 2010
上面的問題持續了3~4年,到底 32 位元與 64位元應用程式好壞也漸漸地有了較明確的選擇。
除非明確地需要大量的記憶體,或者需要長整數,否則32位元就已經足夠。64位元的效能還會有一些些下降。
因此,在 Visual Studio 2010,建立新專案時,Target Platform(平台目標) 預設就是 x86。
但是,AnyCPU 的assembly 執行方式仍然沒有變。
Visual Studio 2012
到了 Visual Studio 2012又有變化。這個時間點,正巧 ARM CPU (也是32bits)也要進來,因此 32bit === x86 時代正式終結。
Visual Studio 2012 建立新專案後的預設選項為 AnyCPU32BitPreferred。
注意一下, Prefer 32-bit 被 disable 掉,是指不能修改,但在.NET Framework 4.5 就可以設定了!
當 assembly 使用的是 AnyCPU 平台目標時,且
- 執行在 32 位元Windows作業系統時,會以 32 位元的方式執行,IL 會被編譯成 x86 的 native code。
- 執行在 64 位元Windows作業系統時,會以 64 位元的方式執行,IL 會被編譯成 x64 的 native code。
- 執行在 ARM Windows作業系統時,會以 32 位元的方式執行,IL 會被編譯成 ARM 的 native code。
因此,Perfer 32-bit 可以說是特地為 ARM 設計的。
結論
AnyCPU 從一開始,到目前其定義仍然沒有變動過。也就是「碰到ppp的作業系統,就執行成ppp的程式」,其中 ppp 可以是 32bit, 64bit, ARM。
改變的是「建立專案時的預設選項」。
也因此,上述 Oracle Client 的問題還是很可能會發生。建議儘可能地明確地指定平台目標(Target Platform),以減少不確定性。