【问题标题】:Why does double free or corruption error not happen at run time for boost ptr_container?为什么 boost ptr_container 在运行时不会发生双重释放或损坏错误?
【发布时间】:2015-06-19 19:22:39
【问题描述】:

我正在测试 boost ptr_containers 并编写了一个小程序如下:

class Test {
    public:
        ~Test() {
            cout << "Test Destructor called" << endl;
         }
};

int main(int argc, char** argv) {

    boost::ptr_map<int, Test> TestContainer;
    boost::ptr_vector<Test> TestVector;
    for (int i=0; i<2; ++i) {
        Test* ptr = new Test();
        TestContainer.insert(i, ptr);
        TestVector.push_back(ptr);
    }

}

一旦我执行程序,“Test Destructor called”会打印四次,程序成功完成。我期待打印会发生 2 次,然后会抛出“doube free ...”错误消息。为什么在上面的情况下没有发生,但它发生在原始指针(Test*)上?

【问题讨论】:

  • 如果您故意编写调用未定义行为的程序,那么任何事情都可能发生,包括“工作”、崩溃等。
  • 双重释放错误是未定义的行为,未定义的行为并不意味着“崩溃”(blog.llvm.org/2011/05/what-every-c-programmer-should-know.html),尽管崩溃是有效的结果。
  • 这是对UB的常见误解。未定义的行为可能意味着不可预测的行为。这就是您无法预测行为的原因。
  • 如何使其成为可预测的行为或如何在我的代码中捕获此类情况?很可能有人可以将相同的指针插入到两个不同的容器中。
  • 停止使用原始指针来保存资源? std::unique_ptr 同时代表所有权和指针。不要通过.get()转让所有权。

标签: c++ memory-management boost


【解决方案1】:

ptr_mapptr_vector 拥有自己的元素。

程序不正确。一次在两个容器中插入相同的元素会导致双重删除。

对已删除指针的删除行为未定义。任何事情都有可能发生。见Undefined Behaviour

使用像 valgrind 这样的工具来捕捉它。


如果您确实想知道,修复此示例的最简单方法是对其中一个容器使用非拥有指针。请务必管理元素的相对生命周期:

#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
#include <map>

class Test {
    public:
        ~Test() {
            std::cout << "Test Destructor called" << std::endl;
         }
};

int main() {

    boost::ptr_vector<Test> TestVector;
    {
        std::map<int, Test*> TestContainer;

        for (int i=0; i<2; ++i) {
            Test* ptr = new Test();
            TestContainer.emplace(i, ptr);
            TestVector.push_back(ptr);
        }
    }

}

【讨论】:

    猜你喜欢
    • 2010-09-05
    • 2014-08-26
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2011-11-18
    • 1970-01-01
    • 2013-05-10
    相关资源
    最近更新 更多