繁体   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