android - 缺少虚拟析构函数内存效应

标签 android c++ virtual

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

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

class Base {}
class Derived {
    int x;
}

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

最佳答案

当然可以。考虑:

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;

现在,这将造成内存泄漏,如std::string sB A::~A 未释放对象- 你需要调用B::~B ,只有当析构函数是虚拟的时才会发生。

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

编辑:

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

所以,换句话说,在类似 PImpl 的地方, 其中Impl类隐藏在一个没有其他人从中派生的源文件中,拥有它是合理的。对于大多数其他情况,这可能是个坏主意。

关于android - 缺少虚拟析构函数内存效应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31664064/

相关文章:

c++ - 如何防止 r 值

c++ - [basic.lookup]/1最后一句是什么意思?

java - 将cpp函数指针转换为java接口(interface)方法

java - 如何解决 Gradle 构建中的存储库证书错误

android - 如何在 MPAndroidChart 中创建一条长红线(限制线)

c++ - 指向虚函数的指针

c++ - 如何修复编译器错误 "class has no member named X"?

C++ 和虚拟析构函数

android - 单击按钮开始新线程

android - 语音实现后的 SearchView 抛出 NullPointerException