Странные проблемы с new / delete в приложении, которое использует мою DLL - PullRequest
4 голосов
/ 29 ноября 2010

извините за загадочный заголовок вопроса. У меня странная проблема, и я понятия не имею, почему это происходит. К счастью, код довольно прост. Но прежде чем мы доберемся до этого, позвольте мне кратко описать мое приложение. Это многопоточное приложение, которое обслуживает большой объем данных. Что-то вроде оперативной базы данных. Можно иметь несколько «баз данных» и загружать / выгружать их во время выполнения. Теперь проблема с освобождением памяти. Пожалуйста, смотрите код ниже (названия классов и т. Д. Изменены, но это не должно иметь значения):

void SS::AllocTree( double*** pba, int i, int d, int b, int split )
{
    this->m_tree = new my_tree( pba, i, d, b, split );
}

void SS::DeallocTree()
{
    delete this->m_tree;
    this->m_tree = NULL;
}

Каждый раз, когда вызывается delete this->m_tree, происходит сбой программы. Трассировка стека выглядит следующим образом:

     mydll.dll!_free_base(void * pBlock=0x0000000008496f70)  Line 109 + 0x14 bytes  C
    mydll.dll!_free_dbg_nolock(void * pUserData=0x0000000008496fa0, int nBlockUse=0x00000001)  Line 1428    C++
     mydll.dll!_free_dbg(void * pUserData=0x0000000008496fa0, int nBlockUse=0x00000001)  Line 1258 + 0xe bytes  C++
    mydll.dll!operator delete(void * pUserData=0x0000000008496fa0)  Line 54 + 0x12 bytes    C++
    mydll.dll!my_tree::`vector deleting destructor'()  + 0x94 bytes C++
    myprog.exe!SS::DeallocTree()  Line 57 + 0x34 bytes  C++
    myprog.exe!SSUnloader(void * arg=0x00000000084d6f80)  Line 1038 C++
    msvcr90d.dll!_callthreadstart()  Line 295   C
    msvcr90d.dll!_threadstart(void * ptd=0x00000000084dad30)  Line 277  C       

Вот трассировка стека для выделения дерева:

     msvcr90d.dll!malloc(unsigned __int64 nSize=0x0000000000000058)  Line 56 + 0x21 bytes   C++
    msvcr90d.dll!operator new(unsigned __int64 size=0x0000000000000058)  Line 59 + 0xa bytes    C++
    myprog.exe!SS::AllocTree(double * * * pba=0x0000000008458ff0, int i=0x00000bde, int d=0x00000010, int b=0x00000008, int split=0x00000001)  Line 52 + 0xa bytes  C++
    myprog.exe!SSLoader(void * arg=0x000000000843cf80)  Line 932    C++
    msvcr90d.dll!_callthreadstart()  Line 295   C
    msvcr90d.dll!_threadstart(void * ptd=0x0000000008440d30)  Line 277  C

Как видите, загрузка / выгрузка выполняется отдельным потоком, специально созданным для этой задачи. Не то, что я не использую какие-либо причудливые вещи, никакие пользовательские кучи или что-либо, никакой пользовательский оператор new / delete в моей dll или моей программе. Я понятия не имею, почему программа заходит в мою DLL и вызывает там удаление, но с новым этого не происходит. Если я изменю DeallocTree(), чтобы он выглядел так:

void SS::DeallocTree()
{
    ::operator delete( this->m_tree );
    this->m_tree = NULL;
}

Тогда все работает нормально. Однако я не уверен, правильно ли это. Должен ли я сделать что-то подобное для оператора нового? И как я могу быть уверен, что эта проблема не встречается больше нигде? Для полноты картины я также прилагаю трассировку стека для этой версии DeallocTree ():

    msvcr90d.dll!operator delete(void * pUserData=0x00000000086f5fa0)  Line 45 + 0xa bytes  C++
    myprog.exe!SS::DeallocTree()  Line 58   C++
    myprog.exe!SSUnloader(void * arg=0x0000000008735f80)  Line 1038 C++
    msvcr90d.dll!_callthreadstart()  Line 295   C
    msvcr90d.dll!_threadstart(void * ptd=0x0000000008739d30)  Line 277  C

Может кто-нибудь объяснить мне, что здесь происходит?

РЕДАКТИРОВАТЬ:
Чтобы уточнить:
my.dll загружается динамически - вывод VS 2008: myprog.exe ': загружен' C: * \ Debug \ mydll.dll ', символы загружены.
Примечание: я правильно использую отладочную версию DLL с отладочной версией моей программы и наоборот с выпуском.
** my_tree объявлено как:
my_tree * m_tree; // дерево

1 Ответ

6 голосов
/ 29 ноября 2010

Ну, похоже, ключ к стекам вызовов.В стеке вызовов «delete» вы заметите, что он вызывает различные функции удаления и т. Д. Непосредственно в mydll.dll.В распределении распределение выполняется msvcr90d.dll.

У вас есть флаг / MDd (или / MD в выпуске), установленный на вашем exe, и / MTd (или / MT в выпуске)на твоих длл.Установите для них оба параметра / MDd (или / MD в выпуске), и ваши проблемы исчезнут ... По сути, вы будете устанавливать как exe, так и dll для выполнения вызовов через dll CRT, вместо того, чтобы пытаться сделать это 2 разнымипути ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...