6

今日、dll と実際のプロジェクトで異なる CRT 設定 (MTd MDd) が原因でヒープの破損が発生しました。私が奇妙なことに気付いたのは、dll のデストラクタを仮想に設定した場合にのみ、アプリケーションがクラッシュしたことです。それについて簡単な説明はありますか?ヒープ上にないメモリを解放できないことはわかりましたが、デストラクタを非仮想として定義した場合の違いはどこにありますか。

少しわかりやすくするためのコード

DLL

#pragma once
class CTestClass
{
public:
    _declspec(dllexport) CTestClass() {};
    _declspec(dllexport) virtual ~CTestClass() {};
};

そして私のプロジェクト

int main(int argc, char* argv[])
{
    CTestClass *foo = new CTestClass;
    delete foo; // Crashes if the destructor is virtual but works if it's not
}
4

3 に答える 3

2

違いがあります

class CTestClass
{
public:
    _declspec(dllexport) CTestClass() {}
    _declspec(dllexport) virtual ~CTestClass() {}
};

__declspec(dllexport) class CTestClass
{
public:
     CTestClass() {}
     virtual ~CTestClass() {}
};

前者の場合、CTestClass::CTestClass() と CTestClass::~CTestClass() の 2 つのメンバ関数のみをエクスポートするようにコンパイラに指示しました。ただし、後者の場合、仮想関数のテーブルもエクスポートするようにコンパイラに指示します。仮想デストラクタを取得したら、このテーブルが必要になります。だから、それがクラッシュの原因かもしれません。プログラムが仮想デストラクタを呼び出そうとすると、関連する仮想関数テーブルでそれを探しますが、適切に初期化されていないため、実際にどこを指しているのかわかりません。デストラクタが仮想でない場合、仮想関数テーブルは必要なく、すべて正常に機能します。

于 2013-11-08T19:29:30.690 に答える