【问题标题】:Derived from two Bases - Delete vector **strange** problem [duplicate]源自两个基 - 删除向量**奇怪**问题[重复]
【发布时间】:2019-05-25 13:39:28
【问题描述】:

我花了好几个小时试图找出问题出在哪里,但这似乎很奇怪。

我以更容易理解的方式重写了我的问题。

当它到达删除的行时,调试器会创建一个断点。

附言。有趣的是,如果我们将 int b1 移到 Base2 中,它就可以工作。

基础1:

#pragma once
class Base1
{
public:
    Base1();
    ~Base1();
    int b1;
};

Base2.h:

#pragma once
#include <iostream>
#include <vector>
class Derived;
class Base2
{
public:
    Base2();
    ~Base2();
    std::vector <std::vector <Base2*>> vec;
    void doSomething(Derived& d);
};

Base2.cpp:

#include "Base2.h"
#include "Derived.h"


Base2::Base2()
{
    //the numbers 1 and 5 does not really metter
    vec.resize(1);
    vec[0].resize(5);
}


Base2::~Base2()
{
}

void Base2::doSomething(Derived& d)
{
    vec[0][d.b1] = new Derived();
    delete vec[0][d.b1];
}

派生:

#pragma once
#include "Base1.h"
#include "Base2.h"
class Derived : public Base1, public Base2
{
public:
    Derived();
    ~Derived();
};

主要:

#include <iostream>
#include "Derived.h"

int main()
{
    Derived d;
    d.b1 = 1;
    d.doSomething(d);
}

【问题讨论】:

  • 我建议你学习智能指针; std::unique_ptrstd::shared_ptr & std::weak_ptr(和朋友;std::make_uniquestd::make_shared)并停止使用手动内存管理(原始newdelete)。
  • 未定义的行为,因为Base2 没有虚拟析构函数。您可以使用Base2 * p = new Derived; delete p; 实现相同的(未定义的行为,可能会或可能不会导致运行时错误)。通过将 int b1 移动到 Base2 碰巧起作用的事实是偶然的 - 行为仍未定义。
  • 谢谢大家。那么为什么如果将 int b1 移动到 Base2 它可以工作呢?我需要一个用于 Base1 的虚拟机吗?或者为什么不呢? (我会看一下重复的问题,那里可能也有答案 - (已编辑:)它没有,因为我们正在谈论两个基地)。
  • 简单地说:undefined behavior is undefined。这也是一本好书;)

标签: c++


【解决方案1】:

Base2 缺少虚拟析构函数。

通过指向其基类的指针删除派生对象,如果该基类没有虚拟析构函数,则会导致未定义的行为。


通常这种UB只会导致丢失析构函数调用(从而导致内存/资源泄漏),但在这种情况下,由于涉及到多重继承,情况就不同了。

当您将new Derived() 返回的指针转换为Base2 * 时,指针的数值会发生变化(由于多重继承)。

delete 调用~Base2() 之后,它随后将指针传递给内存释放函数。
释放函数需要与new 返回的地址相同,这是整个Derived 实例的地址。相反,它获得了Base2 子对象的地址,这是不同的(同样,由于多重继承)。

这与任何其他“尝试delete 未由new 返回的指针” 情况没有什么不同,并且通常会导致崩溃。

如果Base2 有一个虚拟析构函数,则指针将被调整为指向Derived 在释放之前的整个实例。

【讨论】:

  • 这是一个非常有帮助的答案。谢谢!
猜你喜欢
  • 2016-07-15
  • 2011-08-05
  • 2015-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
相关资源
最近更新 更多