为什么没有虚拟析构函数不会导致内存泄漏?

vol*_*twr 3 c++ virtual destructor memory-leaks memory-management

我在玩代码

struct A {
    char a[20000];
    A() { a[0] = 'A'; }
    ~A() {}
};
struct B : A {
    char a[20000];
    B() { a[0] = 'B'; }
    ~B() {}
};
int main() {
    A *pA = new A;
    A *pB = new B;
    delete pA;
    delete pB;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

有人写道(为什么我们需要一个带有动态内存的虚拟析构函数?)它应该引起内存泄漏,但事实并非如此。我使用g ++,然后使用valgrind --leak-check = full --show-leak-kinds = all --track-origins = yes --verbose --log-file = valgrind-out.txt并获取

HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 3 allocs, 3 frees, 132,704 bytes allocated
All heap blocks were freed -- no leaks are possible
Run Code Online (Sandbox Code Playgroud)

我知道有些旧的编译器在类似情况下尝试释放内存时会遇到问题,但是看起来现代C ++在这种情况下可以无缝释放内存。所以我很想知道这怎么可能?也许delete使用OS提供的信息来分配给定的内存块?

编辑。如果我们有空的析构函数和构造函数,对我来说还不清楚是什么会导致UB 删除* pB。一个问题的答案(缺少虚拟析构函数的内存影响)表明没有任何UB。

Bri*_*ian 5

我认为您已经意识到这delete pB是不确定的行为。但是,为什么它不泄漏计算机上的内存?这与实现的动态内存管理的工作方式有关。

这是一种可能:在某些实现上,默认全局operator newoperator delete通过调用C库mallocfree函数来工作。但是free需要在刚传递完void*没有类型或大小信息的a时完成其工作,因此这意味着malloc必须在返回之前在某处“写下”大小。在您的程序中,对的调用new B可能会导致malloc记下的大小B,以便free以后传递指针时,它确切知道要释放多少字节。