[解決済み] GNU GCC (g++)。なぜ複数のdtorが生成されるのですか?
2023-02-26 03:10:25
質問
開発環境は?GNU GCC (g++) 4.1.2
単体テストで「コードカバレッジ(特に関数カバレッジ)」を高める方法を調べているうちに、クラスdtorの一部が複数回生成されているようなことがわかりました。この原因についてご存知の方はいらっしゃいますか?
上記の内容を以下のコードで試して観察してみました。
"test.h"にあります。
class BaseClass
{
public:
~BaseClass();
void someMethod();
};
class DerivedClass : public BaseClass
{
public:
virtual ~DerivedClass();
virtual void someMethod();
};
"test.cpp"にあります。
#include <iostream>
#include "test.h"
BaseClass::~BaseClass()
{
std::cout << "BaseClass dtor invoked" << std::endl;
}
void BaseClass::someMethod()
{
std::cout << "Base class method" << std::endl;
}
DerivedClass::~DerivedClass()
{
std::cout << "DerivedClass dtor invoked" << std::endl;
}
void DerivedClass::someMethod()
{
std::cout << "Derived class method" << std::endl;
}
int main()
{
BaseClass* b_ptr = new BaseClass;
b_ptr->someMethod();
delete b_ptr;
}
上記のコードをビルド(g++ test.cpp -o test)して、どのようなシンボルが生成されたかを確認すると、以下のようになります。
nm --demangle test
以下のような出力が確認できました。
==== following is partial output ====
08048816 T DerivedClass::someMethod()
08048922 T DerivedClass::~DerivedClass()
080489aa T DerivedClass::~DerivedClass()
08048a32 T DerivedClass::~DerivedClass()
08048842 T BaseClass::someMethod()
0804886e T BaseClass::~BaseClass()
080488f6 T BaseClass::~BaseClass()
私の質問は以下の通りです。
1) なぜ複数のdtorが生成されたのですか(BaseClass - 2, DerivedClass - 3)?
2) それぞれのdtorは何が違うのですか?複数のdtorをどのように使い分けるのでしょうか?
C++プロジェクトで100%の関数カバレッジを達成するためには、私のユニットテストでこれらのdtorをすべて呼び出すことができるように、これを理解する必要があるという気がしてきました。
どなたか、上記についてご回答いただけると幸いです。
どのように解決するのですか?
まず、これらの機能の目的については Itanium C++ ABI の下の定義を参照してください。マングル化された名前へのマッピングは5.1.4で示されています。
基本的には
- D2 はベースオブジェクトのデストラクタです。これは、データメンバや非仮想ベースクラスと同様に、オブジェクト自体を破壊します。
- D1 は "完全なオブジェクトのデストラクタです。これはさらに仮想基底クラスを破壊します。
-
D0 は、削除オブジェクトのデストラクタです。これは完全なオブジェクトのデストラクタが行うすべてのことを行い、さらに
operator delete
を呼び出して実際にメモリを解放します。
仮想基底クラスがない場合、D2とD1は同一です。GCCは、十分な最適化レベルにおいて、実際にシンボルを両方とも同じコードにエイリアスします。
関連
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] 0.1fを0にすると、なぜ10倍もパフォーマンスが落ちるのですか?
-
[解決済み] g++とgccの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む
-
[解決済み] コンストラクタ記号のデュアルエミッション