繁体   English   中英

有没有办法检测是否使用非虚拟基础析构函数错误地删除了一个类?

[英]Is there some way to detect if a class is being incorrectly deleted using non-virtual base destructor?

众所周知的场景:

#include <memory>

class A{};
class B : public A {};

int main()
{
    std::unique_ptr<A> a = std::make_unique<B>();
    // bam, when a gets deleted, we have undefined behavior.
    return 0; 
}

而且,只要AB的大小相同,Valgrind甚至都不会发现这样的错误。

是否有一些工具可以捕获这样的错误,至少对于调试版本,或某些习惯用来检测指定类的错误?

对于gcc,您可以指定:

-Wdelete-non-virtual-dtor -Wsystem-headers

要查看by std::default_delete生成by std::default_delete delete-non-virtual-dtor警告,它将如下所示:

/usr/local/include/c++/5.3.0/bits/unique_ptr.h:76:2:警告:删除具有非虚析构函数的多态类型'B'的对象可能会导致未定义的行为[-Wdelete-non virtual-dtor] delete __ptr;

生活

顺便说一句。 您的示例类在基类中至少缺少一个虚函数。

[编辑]

把它变成错误使用:

 -Werror=delete-non-virtual-dtor -Wsystem-headers 

我强烈认为,应该严格区分“基于价值的”类和“基于OO”的类(缺乏更好的术语)。

基于值的类应该没有公共基础,并且通常应该支持复制语义(除非专门设计为禁用复制)。 这些类的对象除了它们的值之外没有其他身份。 它们可以与副本互换。

基于OO的类应该具有虚拟析构函数,并且永远不应该公开访问复制成员。 只能通过虚拟clone方法复制此类的对象。 这些对象具有与其值不同的标识。

应该没有具有非虚拟析构函数或公共副本/移动ctor或公共副本/移动赋值运算符(在基础中)的公共基类。

如果保持这种分离,则不会通过非多态基指针进行对象切片或删除。

不幸的是,没有工具(我知道)有助于保持这种分离。 所以你需要在继承的同时进行尽职调查。 这很简单。 它是否具有虚拟dtor 无法访问/删除的副本ctor和副本分配? 你可以公开继承。 没有? 避免潜在的混乱,使用组合或私人继承。

为继承而设计的好类将使其复制成员受到保护,以便于在后代类中进行克隆。

不幸的是,对于第三方课程,您没有选择权,因为作者通常会将复制成员公开,因此仍存在对象切片的风险。 但是你不会有通过基指针不正确删除的风险。

TL; DR没有工具,只有程序员的尽职调查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM