缺少虚拟析构函数内存效果 [英] Missing Virtual Destructor Memory Effects

查看:34
本文介绍了缺少虚拟析构函数内存效果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据标准,缺少虚拟析构函数的多态会导致未定义的行为.实际上,它确实会导致在删除父类时不会调用派生类的析构函数.但是,它是否也会导致任何常见编译器/系统中的内存泄漏?我对 Android/Linux 上的 g++ 特别感兴趣.

According to the standard, polymorphism with a missing virtual destructor leads to undefined behavior. In practice, it really leads to the destructor for the derived class not being called when the parent class is deleted. However, does it also lead to memory leaks in any common compilers/systems? I'm particularly interested in g++ on Android/Linux.

具体来说,我指的是删除派生类的内存是否会以某种方式泄漏.考虑:

Specifically, I'm referring to whether the deletion of memory for the derived class will somehow leak. Consider:

class Base {}
class Derived {
    int x;
}

如果我删除一个 Base* 到一个 Derived,我会泄漏 4 个字节吗?或者内存分配器是否已经知道根据分配需要释放多少字节?

If I delete a Base* to a Derived, will I leak 4 bytes? Or does the memory allocator already know how many bytes to free based on the allocation?

推荐答案

它当然可以.考虑:

class A
{
public:
 virtual void func() {}
};

class B : public A
{
public:
   void func() { s = "Some Long String xxxxxx"; }
private:
   std::string s;
   // destructor of B will call `std::string` destructor.
};

A* func(bool b)
{
   if (b)
       return new B;
   return new A;
}

... 
   A* a = func(true);
...
   delete a;

现在,这会造成内存泄漏,因为 B 对象中的 std::string s 没有被 A::~A - 你需要调用 B::~B,这只会在析构函数是虚拟的时候发生.

Now, this will create a memory leak, as std::string s in the B object is not freed by A::~A - you need to call B::~B, which will only happen if the destructor is virtual.

请注意,这适用于我所知道的所有编译器和所有运行时系统(所有常见的和一些不那么常见的).

Note that this applies to ALL compilers and all runtime systems that I'm aware of (which is all the common ones and some not so common ones).

基于更新的实际问题:内存取消分配是根据分配的大小发生的,因此如果您可以保证永远不会因为类的构造/使用而发生单个分配,那么没有分配是安全的一个虚拟析构函数.然而,如果基类的客户"可以创建他/她自己的扩展类,这会导致有趣的问题.将派生类标记为 final 将防止它们被进一步派生,但是如果基类在其他人可以包含的头文件中可见,那么您就有可能有人从 final 派生他们自己的类code>Base 做一些分配的事情.

Based on the updated actual question: Memory de-allocation happens based on the allocated size, so if you can GUARANTEE that there NEVER is a single allocation happening because of the construction/use of the class, then it's safe to not have a virtual destructor. However, this leads to interesting issues if a "customer" of the base-class can make his/her own extension classes. Marking derived classes as final will protect against them being further derived, but if the base class is visible in a header-file that others can include, then you run the risk of someone deriving their own class from Base that does something that allocates.

因此,换句话说,在诸如 PImpl 之类的东西中,Impl 类隐藏在没有其他人从中派生的源文件中,有这个是合理的.对于大多数其他情况,这可能是个坏主意.

So, in other words, in something like a PImpl, where the Impl class is hidden inside a source file that nobody else derives from, it's plausible to have this. For most other cases, probably a bad idea.

这篇关于缺少虚拟析构函数内存效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆