3

I am trying to make a DLL file compatible with different compiler configurations (Debug, Release,..). In order to make sure that an object is removed the right way I managed to write a pointer wrapper class that uses a compiled delete operator whenever I take an object of the DLL and run out of scope.

I am perfectly fine with this but my program crashes when I try to delete memory that I allocated in the very same method/program.

Here is some sample code compiled in a standard Release mode:

header

template <typename T>
class API mwCompatibleObject
{
public:

    //! Constructor
    mwCompatibleObject();

    //! Destructor
    virtual ~mwCompatibleObject();
};

source code

template < typename T >
mwCompatibleObject< T >::mwCompatibleObject() {}

template <typename T>
mwCompatibleObject<T>::~mwCompatibleObject() {}

Note: API is defined as export/import.

Now I use this very class in a Debug mode application where I create an instance and delete it right away.

mwCompatibleObject<double> * obj = new mwCompatibleObject<double>();
delete obj;

Executing the delete operator gives an access violation at mlock.c line 376.

Here is a copy of the callstack:

ntdll.dll!7721e3be()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
msvcr80d.dll!_unlock(int locknum=4)  Line 376   C
msvcr80d.dll!_heap_alloc_dbg(unsigned int nSize=0, int nBlockUse=2968120, const char * szFileName=0x2e2ed26c, int nLine=1638180)  Line 477 + 0x7 bytes  C++
msvcr80d.dll!_heap_alloc_dbg(unsigned int nSize=0, int nBlockUse=2968120, const char * szFileName=0x2e2ed26c, int nLine=1638180)  Line 474 + 0xc bytes  C++
00300000()  
msvcr80d.dll!malloc(unsigned int nSize=2968120)  Line 154 + 0x15 bytes  C++
5axutil.dll!100b5d09()  
Integrator3.exe!main()  Line 54 + 0x34 bytes    C++

I can't jump into that line or anything but I managed to get a look at the Assembler code which proves my observation that it has to do with the destructor.

Is there a general problem with virtual functions/destructors when trying to make a DLL compatible?

4

1 に答える 1

4

コンパイラがテンプレートの使用法に基づいて型を生成するため、テンプレート定義をエクスポートすることはできません。それらをヘッダーファイルにインライン化するか、このようなことを行うことができますが、テンプレートのインスタンス化を事前に宣言する必要があります。

また、C ++では、コンストラクタとデストラクタを実際に呼び出したい場合は特に、Cの関数と関数をnew優先deleteすることに注意してください。mallocfree

編集:

テンプレートをインライン化することは、エクスポートを試みるよりも望ましいと真剣に検討します。また、仮想デストラクタは、クラスが基本クラスになるか、仮想メソッドを含む場合にのみ必要であることに最初は気づきませんでした。何も入っていないvtableがあるのはなぜですか?

template <typename T>
class mwCompatibleObject // no need for export if inlined in header
{
public:
    //! Constructor
    mwCompatibleObject() {}
    //! Destructor (don't need virtual unless it's a base class or has virtual methods)
    ~mwCompatibleObject() {}

    //! Some public method
    void DoSomething(const T& withSomething)
    {
        // ... yata yata
    }
private:
    T m_member;
};

さらに編集:

テンプレートサポートのエクスポートは、最終化されたときに新しいC ++標準から完全に削除される(非推奨ではなく、削除される)ことがわかりました。ヘッダーファイルのインラインテンプレートは、コンパイラーが実装し、非常に近い将来に許可する唯一のソリューションになるため、今すぐこの方法でそれらを作成することに慣れてください。C++0xに関するハーブサッターの質問と回答を参照してください

于 2011-05-27T15:22:37.290 に答える