Виртуальный деструктор вызывает нарушение прав доступа - PullRequest
3 голосов
/ 27 мая 2011

Я пытаюсь сделать файл DLL совместимым с различными конфигурациями компилятора (Debug, Release, ..).Чтобы убедиться, что объект удален правильно, мне удалось написать класс-оболочку указателя, который использует скомпилированный оператор удаления всякий раз, когда я беру объект DLL и выхожу из области видимости.

Я отличнохорошо, но моя программа падает, когда я пытаюсь удалить память, выделенную в том же методе / программе.

Вот пример кода, скомпилированного в стандартном режиме Release:

header

template <typename T>
class API mwCompatibleObject
{
public:

    //! Constructor
    mwCompatibleObject();

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

исходный код

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

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

Примечание: API определяется как экспорт / импорт.

Теперь я использую этот самый класс в приложении режима отладки, где я создаюи сразу же удалите его.

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

Выполнение оператора удаления приводит к нарушению доступа в строке 376 mlock.c.

Вот копия стека вызовов:

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++

Я не могу перейти на эту строку или что-то еще, но мне удалось взглянуть на код ассемблера, который подтверждает мои наблюдения, что это связано с деструктором.

Есть ли общая проблемас виртуальными функциями / деструкторами при попытке сделать DLL совместимой?

1 Ответ

4 голосов
/ 27 мая 2011

Вы не можете экспортировать определение шаблона, так как компилятор генерирует типы на основе использования шаблона.Вы просто вставляете их в заголовочный файл или , вы можете сделать что-то вроде этого , но для этого необходимо объявить экземпляр вашего шаблона заранее.

Также обратите внимание, что в C ++ предпочитают new и delete над *Функции 1007 * и free из C, особенно если вы на самом деле хотите, чтобы конструкторы и деструкторы вызывались.

Редактировать:

Я бы серьезно посчитал встраивание шаблона предпочтительнымна любую попытку экспорта.Также я не смог отметить, что виртуальные деструкторы нужны только в том случае, если ваш класс будет базовым или содержит виртуальные методы.Почему в 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

...