我的C++代码中是否有一些内存泄漏

Are there some memory leaks in my C++ code?

本文关键字:内存 泄漏 是否 C++ 代码 我的      更新时间:2023-10-16
#include <iostream>
class B {
public:
    B() {}
    void p() const { std::cout << "B::pn"; }
    void q() const { std::cout << "B::qn"; }
    int b;
};
class D : public B { 
public:
    D() {}
    virtual void p() const { std::cout << "D::pn"; }
    virtual void q() const { std::cout << "D::qn"; }
    int d;
};
int main(int argc, char const *argv[])
{
    B b;
    D d;
    B* pb = new B;
    B* pd = new D;
    D* pd2 = new D;
    b.p(); b.q();
    d.p(); d.q();
    pb->p(); pb->q();
    pd->p(); pd->q();
    pd2->p(); pd2->q();
    delete pb;
    delete pd;
    delete pd2;
    return 0;
}

似乎delete pd内存泄漏.我猜pd不是指向D的指针,所以当我delete它时,它不会调用D的析构函数,而是调用B的析构函数。但是,我不知道确切的原因。谁能帮助我?谢谢。

代码中可能存在内存泄漏。 但同样,可能没有。

如评论中所述,此序列

B* pd = new D;
delete pd;

在您的代码中(无论您提供的所有其他代码如何(给出了未定义的行为,因为B没有virtual析构函数。

当行为未定义时,任何事情都可能发生,包括内存泄漏或任何其他您可能想象或可能不会想象的事情。

如果你为 B 声明一个 virtual 析构函数,并定义它,这样它就不会泄漏内存(例如 virtual ~B() {} (,则您的代码将具有明确定义的行为。 使用运算符 new 创建的所有对象都使用运算符 delete 正确销毁,因此 - 如果B具有虚拟析构函数 - 它们都不会导致内存泄漏。

你怎么知道 D 的析构函数没有被调用?您的示例代码甚至没有析构函数。事实上,它不会像注释中指出的那样调用 D 的析构函数。基类中没有虚拟析构函数是不好的。

尝试以下示例,

#include <iostream>
class B {
public:
    B() {}
    virtual ~B() { std::cout << "B::dtorn"; }
    void p() const { std::cout << "B::pn"; }
    void q() const { std::cout << "B::qn"; }
    int b;
};
class D : public B {
public:
    D() {}
    virtual ~D() { std::cout << "D::dtorn"; }
    virtual void p() const { std::cout << "D::pn"; }
    virtual void q() const { std::cout << "D::qn"; }
    int d;
};
int main(int argc, char const *argv[])
{
    B b;
    D d;
    B* pb = new B;
    B* pd = new D;
    D* pd2 = new D;
    b.p(); b.q();
    d.p(); d.q();
    pb->p(); pb->q();
    pd->p(); pd->q();
    pd2->p(); pd2->q();
    delete pb;
    delete pd;
    delete pd2;
    return 0;
}

对于您的问题,您的实现中存在泄漏,因为 pd 被删除,可能不会调用以 D 的 dtor 编写的内存清理。

B* pb = new B;
//B::B()
B* pd = new D;
//B::B()   <-- constructor called
//D::D()   <-- constructor called
D* pd2 = new D;
//B::B()
//D::D()
....
pd->p(); pd->q();
//B::p
//B::q
....
delete pb;
//~B::B()
delete pd;
//~B::B()  <-- leaks here
delete pd2;
//~D::D()
//~B::B()

您应该对类 B 的析构函数使用关键字"virtual":

private:
virtual ~B() {}