2016-03-27 7 views
8

非常によく知られているシナリオ:非仮想ベースデストラクタを使用してクラスが誤って削除されているかどうかを検出する方法はありますか?

#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; 
} 

また、いなくてもValgrindのは、ABの大きさが同じであることは、このようなエラーをキャッチすることができます。

少なくともデバッグビルドや、指定されたクラスのエラーを検出するイディオムでこのようなエラーをキャッチできるツールはありますか?

+1

機能を使いたいですか?それ以外の場合は、継承を無効にすることができます:http://stackoverflow.com/a/12319547/1287254 – Shaggi

+0

素晴らしい!これは私が今解決している実用的な問題を解決しますが、私は好奇心の外に一般的な事例を知りたいと思います。 –

+1

依存していますが、[std :: has_virtual_destructor](http://en.cppreference.com/w/cpp/types/has_virtual_destructor)が探しているものの一部かもしれません。 – kec

答えて

5

GCCについて次のように指定できます。

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

delete-non-virtual-dtor警告がby std::default_deleteを生成見るために、次のようになります

/usr/local/include/c++/5.3.0/bitsを/unique_ptr.h:76:2:警告:ポリモーフィッククラス型のオブジェクトを削除する非仮想デストラクタを持つ 'B'は未定義の動作を引き起こす可能性があります[-Wdelete-non-virtual-dtor] delete __ptr;ところで

live

。サンプルクラスには、基底クラスに少なくとも1つの仮想関数がありません。

エラーの使用にそれをオンにし、[編集]

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

'unique_ptr'を使っているときに仮想デストラクタが必要ないと思います。 – 0x499602D2

+1

@ 0x499602D2あなたはshared_ptrを考えています。これは、Deleterをタイプ消去します。 Unique_ptrには、基本クラスに仮想デストラクタが必要です。 –

+0

これは、仮想関数を追加する場合にのみ発生しますが、-WeffC++を使用すると、より早く問題を把握できます。 –

1

それは1が厳密に独立した「値ベース」のクラスとは「OOベース」のクラスを(必要があることを私の強い意見でありますより良い言葉の欠如)。

バリューベースのクラスは公開拠点を持たず、通常はコピーセマンティクスをサポートする必要があります(コピーを無効にするように特別に設計されていない限り)。そのようなクラスのオブジェクトには、その値とは別の識別情報がありません。それらはコピーと互換性があります。

OOベースのクラスには仮想デストラクタが必要であり、一般にアクセス可能なコピーメンバを決して使用しないでください。そのようなクラスのオブジェクトは、仮想cloneメソッドを介してのみコピーする必要があります。このようなオブジェクトは、その値とは別個のIDを持ちます。

非仮想デストラクタ、パブリックコピー/ムーブctorまたはパブリックコピー/ムーブ代入演算子(ベース内)を持つパブリックベースを持つクラスは存在しません。

この分離を維持すると、非ポリモフィックベースポインタを使用したオブジェクトのスライスまたは削除で事故が発生しなくなります。

残念ながら、この分離を維持するのに役立つツールはありません。それで、あなたは相続しながらデューデリジェンスを行う必要があります。それは本当に簡単です。それは仮想のdtor アクセス不可能な/削除されたコピーctorとコピー割り当てを持っていますか?あなたは公に継承することができます。いいえ?潜在的な混乱、構成の使用、または個人の継承を避ける。

継承のために設計された優れたクラスは、子孫クラスでの複製を容易にするために、コピーメンバーを保護します。

残念ながら、第三者のクラスでは選択肢がありません。作成者は一般にコピーメンバーを公開しているので、オブジェクトをスライスする危険性があります。しかし、あなたはベースポインタを介して不適切な削除のリスクがありません。

TL; DRツールなし、プログラマーのデューデリジェンスのみ。

関連する問題