[英]Why do I get a warning for an unaligned pointer but not a reference
我有一個項目要從 32 位 Windows 移植到 64 位,其中包括可以簡化如下的代碼:
void FuncA(double &x)
{
x = 0;
}
void FuncB(double *x)
{
*x = 0;
}
#pack(1)
struct
{
char c;
double x;
} MyStruct;
#pack();
void MyFunc()
{
MyStruct M;
FuncA(M.x); // This is OK
FuncB(&M.x); // This generates a warning C4366
}
在針對 64 位的 VS2010 SP1 下編譯時,使用打包結構的成員調用FuncB
生成以下警告:
警告 C4366:一元“&”運算符的結果可能未對齊
而調用FuncA
則不然。 我原以為這兩種情況都會編譯成幾乎相同的代碼。 引用是否比等效指針更安全? 還是 MSVC 根本沒有在應該發出警告的地方發出警告? 該項目需要維護結構包裝,所以我的選擇是將FuncB
更改為
void FuncB(__unaligned double *x)
{
*x = 0;
}
或者在所有這些情況下簡單地使用FuncA
。 后者更可取,因為它更便攜,但我想知道它是否會起作用,或者參考案例中缺少警告只是編譯器的一個缺點?
編輯:此錯誤的 Microsoft 幫助條目在此處。 __unaligned幫助表明不注意此警告將導致在 Itanium 處理器上引發異常。 對 MSDN 的進一步搜索表明可能存在圍繞未對齊引用的問題。 雖然這可能不會給我當前的用戶帶來問題,但如果 Itanium 架構在未來得到更廣泛的使用,我可能會遇到支持噩夢。 現在計划為所有使用壓縮結構的函數添加特定的包裝器,以避免指針和 __unaligned 關鍵字。
引用和指針幾乎是一樣的東西(可以這么說),所以從安全的角度來看,它沒有什么不同。 這可能更多是一種疏忽和/或編譯器不太關心引用,因為它們不能在 C++ 環境之外傳遞(盡管我傾向於認為這只是一種疏忽)。
也可能是編譯器更關心指針,因為指針更有可能用於性能,您希望在一系列double
值上進行迭代(例如,通過分配比結構本身使用的更多的空間,並進一步存儲它后面的double
值) - 你不能用引用來做到這一點。 由於未對齊訪問至少比對齊訪問慢,這會對性能產生影響,並且在某些系統中,它會導致操作系統陷阱,這將“修復”未對齊訪問(以幾個命令的速度)比普通的對齊訪問慢),或者操作系統只是說“您的程序導致了未對齊的訪問,我正在殺死它”。
多線程也存在問題,因為未對齊的訪問可能不會自動更新數據。 當然,對於線程之間共享的數據,您應該使用std::atomic
或類似方法。
x86 完全能夠從未對齊的地址讀取double
精度值。 我認為 Itanium 不是,但我懷疑您無論如何都不會使用該處理器,從統計上講。 其他較舊的體系結構(例如 Alpha)可能會在讀取未對齊的內存時出現問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.