【问题标题】:Zeroing memory used by STL containersSTL 容器使用的内存归零
【发布时间】:2012-08-08 20:50:58
【问题描述】:

我想使用 STL 容器(加上 std::basic_string)将密钥或密码临时存储在内存中,并且我想在完成后将内存归零。

我最初计划使用在自定义分配器上参数化的 STL 容器,该分配器将 allocator::deallocate 中的内存归零,但我假设容器可以使用并非来自指定分配器的内存。例如,std::vectorstd::string 包含用于小分配的固定大小数组成员似乎是合理的。

我的担心是否正确,我应该(叹息)自己编写容器吗?

【问题讨论】:

  • 我不明白,你为什么不使用向量,在让它超出范围之前,只做一个 memset(myVec, 0x00, myVec.size())?
  • 对于std::vector,您必须跳过燃烧的箍以满足异常要求,并且仍然将数据存储在矢量对象本身中。对于std::string,在对象中存储数据不仅是可能的,而且相当普遍。
  • @AntonRoth:因为如果有人调用std::vector::resizestd::vector::push_back 并导致std::vector 分配一个新的内存块并复制现有缓冲区会发生什么?
  • 是的,我在较早的答案中写道,我删除了,因为我不太确定这个问题,你可以分配比以往更多的内存,并将其归零。还是使用的内存很关键?
  • 我在这里遗漏了什么吗?让清理存储对象而不是容器的责任不是更有意义吗?那么只是让容器存储一个类项,其析构函数会自行清理吗?当向量调整大小时,不要复制构造函数,然后调用析构函数...?

标签: c++


【解决方案1】:

我会将std::vector 与一个自定义分配器一起使用,该分配器执行归零。根据May std::vector make use of small buffer optimization? 的答案,它不能使用小缓冲区优化,因此,使用自定义分配器,你应该是安全的。

如果你更进一步,使用该分配器来分配向量,然后使用智能指针来确保它被正确释放(或手动执行),甚至是向量的内部内容(例如大小) 将被消灭。

【讨论】:

    【解决方案2】:

    您可以通过使用原始内存和放置 new 分配字符串/向量来做到这一点,当您完成它时,调用析构函数、零内存并释放原始内存。

    【讨论】:

    • 100%真实且完全合理的方式!但不可重用,并且在某种程度上绕过了 STL 来代替核心​​ C++ 运算符和内存黑客。通过编写自定义分配器,您所写的所有内容都可以很好地包装,请参阅 DateS 的答案
    • @quetzalcoatl:它使用的是 stl,我的意思是把字符串/向量对象放在原始内存中。
    • 不,您必须使用分配器。由向量/字符串分配的堆内存不会受到您将对象内存清零的影响。即使您明确地将向量中的值清零,向量的大小调整操作仍然可能留下副本。
    • @Eclipse:我假设 Dani 的意思是结合使用 placement-new 和自定义分配器。
    • @quetzalcoatl:是的,如果你同时使用自定义分配器和放置 new,那么你可以确定你已经覆盖了所有内存。
    【解决方案3】:

    使用自定义字符串类,在其析构函数中将内存缓冲区归零。

    class zeroed_string : public std::string
    {
    public:
        ~zeroed_string()
        {
            for (int i = 0; i < size(); ++i)
                (*this)[i] = 0;
        }
    // ...
    };
    

    【讨论】:

    • 我不认为 std::string 应该用作基类,否则它将具有虚拟析构函数。顺便说一句,您的答案与下面的 -4 相同
    • 正如我在另一个(现已删除)答案中提到的,如果 std::string 被调整大小并需要分配新的内存块,这将不起作用。该答案的其他 cmets 也指出它不适用于 COW 实现。
    • @BЈовић 如果您打算多态地使用它,那是真的,但在这种情况下,您不是。我认为人们在这一点上过于偏执了。
    • @jamesdlin,我的回答是最简单的方法,但建议仍然有效 - 使用自定义字符串类来强制执行您需要的安全性。如果std::string 不行,就从头写一个。
    • 这是经过测试的吗?原则上,编译器可以优化这个循环,因为它(可能)没有可观察的行为。
    猜你喜欢
    • 2015-01-15
    • 2012-08-04
    • 2016-06-07
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2013-06-18
    • 2011-08-25
    • 1970-01-01
    相关资源
    最近更新 更多