[英]Avoiding strict aliasing violation in hash function
我如何避免嚴格違反別名規則,嘗試修改sha256函數的char*
結果。
計算哈希值:
std::string sha = sha256("some text");
const char* sha_result = sha.c_str();
unsigned long* mod_args = reinterpret_cast<unsigned long*>(sha_result);
比得到2個64位:
unsigned long a = mod_args[1] ^ mod_args[3] ^ mod_args[5] ^ mod_args[7];
unsigned long b = mod_args[0] ^ mod_args[2] ^ mod_args[4] ^ mod_args[6];
比通過concat獲得結果有兩個方面:
unsigned long long result = (((unsigned long long)a) << 32) | b;
聽起來令人沮喪,但唯一真正可移植,符合標准和有效的方法是通過memcpy()
。 使用reinterpret_cast
違反了嚴格的別名規則,並且當您從未寫入的成員中讀取時,使用union
(通常建議)會觸發未定義的行為。
但是,由於大多數編譯器都會優化memcpy()
調用,所以這並不像聽起來那樣令人沮喪。
例如,下面的代碼帶有兩個memcpy()
:
char* foo() {
char* sha = sha256("some text");
unsigned int mod_args[8];
memcpy(mod_args, sha, sizeof(mod_args));
mod_args[5] = 0;
memcpy(sha, mod_args, sizeof(mod_args));
return sha;
}
產生以下優化的裝配:
foo(): # @foo()
pushq %rax
movl $.L.str, %edi
callq sha256(char const*)
movl $0, 20(%rax)
popq %rdx
retq
很容易看到,那里沒有memcpy()
-值被“就地”修改了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.