簡體   English   中英

如何安全地將 std::array 歸零?

[英]How to safely zero std::array?

我正在嘗試將 class 析構函數中的std::array安全歸零。 safe開始,我的意思是我想確保編譯器永遠不會優化這個歸零。 這是我帶來的:

template<size_t SZ>
struct Buf {
    ~Buf() {
        auto ptr = static_cast<volatile uint8_t*>(buf_.data());
        std::fill(ptr, ptr + buf_.size(), 0);
    }

    std::array<uint8_t, SZ> buf_{};
};

此代碼是否按預期工作? 在任何情況下,該volatile關鍵字都會阻止編譯器進行優化嗎?

C++ 標准本身並沒有做出明確的保證。 它說:

通過 volatile 泛左值訪問的語義是實現定義的。 ...

[注 5: volatile 是對實現的提示,以避免涉及 object 的激進優化,因為 object 的值可能會通過實現無法檢測到的方式進行更改。 此外,對於某些實現,易失性可能表明需要特殊的硬件指令才能訪問 object。 有關詳細語義,請參見 [intro.execution]。 通常,在 C++ 中,volatile 的語義與在 C 中的語義相同。 ——尾注]

Despite the lack of guarantees by the C++ standard, over-writing the memory through a pointer to volatile is one way that some crypto libraries clear memory - at least as a fallback when system specific function isn't available.

PS我建議改用const_cast ,以避免意外轉換為不同的類型,而不是不同的限定相同類型:

auto ptr = const_cast<volatile std::uint8_t*>(buf_.data());

隱式轉換也有效:

volatile std::uint8_t* ptr = buf_.data();

用於此目的的系統特定函數是SecureZeroMemory中的 SecureZeroMemory 和一些 BSD 和 glibc 中的explicit_bzero _bzero。

C11 標准有一個可選的 function memset_s用於此目的,它也可能在 C++ 中可供您使用,但當然不能保證可用。

有一個提案P1315將類似的 function 引入 C++ 標准。

一種選擇是使用std::atomic_ref進行寬松的原子存儲,編譯器無法省略。 C++20 示例:

#include <cstdint>
#include <atomic>
#include <array>

template<class Array>
void clear(Array& a) {
    for(auto& e : a) 
        std::atomic_ref{e}.store(0, std::memory_order_relaxed);
}

void f(std::array<uint32_t, 32>& a) {
    clear(a);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM