【发布时间】:2023-04-04 06:28:02
【问题描述】:
我正在编写一些处理密码机密的代码,并且我创建了一个自定义的 ZeroedMemory 实现 std::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)?
【问题讨论】:
-
std::array不在堆上分配任何内存,因此不需要分配器。它还需要是一个聚合,因此不能具有可以采用分配器参数的用户定义构造函数。std::tuple采用分配器只是为了将其传递给其组件的构造函数,如果他们愿意的话;分配器不用于其他任何事情。std::tuple<uint8_t, uint8_t>不会将其分配器用于任何事情。 -
@IgorTandetnik ...这是有道理的。我想我需要将它提升为基于堆的对象,这意味着类似于
std::shared_ptr<std::array<uint8_t, 32>>,此时我可以使用自定义删除器。我总是返回std::unique_ptr,以便调用者可以选择他们自己的指针风格,我很担心,因为该类型需要(内部)删除器作为参数,但看起来std::shared_ptr没有这个问题。 -
好吧,如果您担心客户滥用,
shared_ptr可以是released。 -
@IgorTandetnik Footguns 是可以的,只要它们有足够的安全性。我的工作不是阻止客户不安全地释放内存,就像阻止他们将缓冲区的内容通过电子邮件发送给中国人一样。我的工作就是确保他们不会意外。
-
@IgorTandetnik 另外,
std::shared_ptr没有release();它有一个reset(),但它仍然调用删除器。
标签: c++ c++17 allocator c++20 stdarray