分配器感知的"std::array"样式容器?

Allocator-aware `std::array`-style container?

本文关键字:quot 样式 std 感知 分配器 array      更新时间:2023-10-16

我正在编写一些处理加密机密的代码,并且我创建了一个自定义ZeroedMemorystd::pmr::memory_resource实现,该实现处理在释放时清理内存并使用您必须使用的魔法进行封装,以防止优化编译器省略操作。这个想法是为了避免专门的std::array,因为缺少虚拟析构函数意味着类型擦除后的销毁会导致内存被释放而不被清理。

不幸的是,我后来意识到std::array不是AllocatorAwareContainer。我std::pmr::polymorphic_allocator的方法有点误导,因为显然std::array中没有空间来存储指向特定分配器实例的指针。尽管如此,我仍然无法理解为什么不允许使用std::allocator_traits<A>::is_always_equal::value == true的分配器,并且我可以轻松地将我的解决方案重新实现为通用Allocator,而不是更易于使用的std::pmr::memory_resource......

现在,我通常只能使用std::pmr::vector代替,但std::array的一个很好的功能是数组的长度是类型的一部分。例如,如果我正在处理一个 32 字节的密钥,我不必进行运行时检查来确保某人传递给我的函数的std::array<uint8_t, 32>参数实际上是正确的长度。事实上,这些很好地投射到一个const std::span<uint8_t, 32>,这大大简化了编写需要与 C 代码互操作的函数,因为它们使我能够基本上免费处理来自任何来源的任意内存块。

具有讽刺意味的是,std::tuple需要分配器...但我不寒而栗地想象处理 32 字节std::tuple<uint8_t, uint8_t, uint8_t, uint8_t, ...>所需的 typedef .

那么:是否有任何标准类型可以容纳固定数量的同质类型项目,std::array,但分配器感知(并且最好将项目存储在应急区域中,因此可以向下投射到std::span)?

您需要编译器和操作系统的合作才能使这样的方案起作用。P1315是一个解决编译器/语言方面的建议。至于操作系统,您必须确保内存永远不会分页到磁盘等,以便真正实现零内存。

这听起来像是一个XY问题。 您似乎滥用了分配器。 分配器用于处理运行时内存分配和释放,而不是挂钩堆栈内存。 您正在尝试执行的操作(使用后将内存归零)实际上应该使用析构函数来完成。 您可能希望为此编写一个类Key

class Key {
public:
// ...
~Key()
{
secure_clear(*this); // for illustration
}
// ...
private:
std::array<std::uint8_t, 32> key;
};

您可以轻松实现迭代器和跨度支持。 而且您不需要玩分配器。

如果要减少样板代码并使新类自动迭代器/跨度友好,请使用继承:

class Key :public std::array<std::uint8_t, 32> {
public:
// ...
~Key()
{
secure_clear(*this); // for illustration
}
// ...
};