Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Вызов "new" в DLL; "delete" - в EXE == ERROR


Автор: mr.DUDA 27.7.2003, 23:04
Кто-нибудь может предположить, почему когда вызван "стандартный" оператор new (мелкософт VC++ 6.0) внутри экспортируемой функции - нельзя освобождать выделенный блок вне DLL (будет исключение хипа) ?

Ситуация такова:
1) в EXE есть глобальный указатель void *ptr
2) эта EXE загружает DLL с одной экспортируемой ф-цией
3) экспортируемая ф-ция получает указатель ч/з аргумент, выделяет блок памяти 10 байт -- "ptr=new char[10]"
4) DLL выгружается
5) в EXE вызывается "delete ptr" ======> получаем красное окно.

Что сделано неправильно? В MSDN не сказано ничего о том, что для DLL и вызывающей EXE'шки существуют разные хипы. Даже адреса блоков памяти похожи, если выделить блок в EXE, а потом сразу же - в DLL.

Кто знает, плиз help confused.gif

Автор: RAN 28.7.2003, 00:16
Нет, ошибка не в куче. DLL выделяет память от имени твоего процесса, так что удалять можешь смело.
Проверь значение ptr в DLL и после возврата в EXE. Возможно ошибка в способе передачи параметра, ptr надо передавать по ссылке
Код

void DLLFunction(void*& ptr)
{
   ptr = new char[10];
}


Автор: mr.DUDA 28.7.2003, 10:45
УРА !!!
Нашел источник ошибки (Sorry за сильно упрощенный вопрос - оказалось, что проблема формулируется не так).

НЕ делайте деструкторы виртуальными если объект создается в DLL а удаляется уже тогда, когда DLL выгружена ! Куча и в самом деле только одна, а вот сегмент кода - разный для EXE и DLL. Поэтому такой код приведет к ошибке:

test_dll.dll:
Код

class CSome
{
public:
CSome() {}
virtual ~CSome() {}
};

typedef CSome* LPSOME;

extern "C" __declspec(dllexport) LPSOME Some()
{
return new CSome;
}



test.exe:
Код

class CSome
{
public:
CSome() {}
virtual ~CSome() {}
};

typedef CSome* LPSOME;

BOOL CTest_exeApp::InitInstance()
{
HMODULE hmod=LoadLibrary("test_dll.dll");
LPSOME (*pfn)() = (LPSOME (*)())GetProcAddress(hmod, "Some");
LPSOME ob=(*pfn)();
FreeLibrary(hmod);
delete ob; // будет EXCEPTION !!!!!!!!!!!!!!!!!!
return FALSE;
}


А вот если поубирать "virtual" у деструкторов в EXE и в DLL - все будет Ok, т.к. физическое расположение функции CSome::~CSome будет в EXE (а не в DLL, как в приведенном примере).

Если у кого-то появятся похожие траблы - пишите !

Автор: SMILic 16.4.2004, 22:11
привет, ты в паскале шариш??? biggrin.gif
Добавлено @ 22:15
эй мне просто помощь нужна а я здесь впервые, вот и не знаю куда потикнутся ??? посодействуй хоть крапаль, хотя бы ради солидарности baaa.gif

Автор: Fantasist 16.4.2004, 22:50
На самом деле есть еще такая фигня, как менеджер памяти. То есть для выделения куска памяти new может обращатся к встроенному менеджеру памяти (как и delete для освобождения), который для dll и для exe может быть своим. Тут все зависит от реализации RTL. В Делфи происходит именно таким образом, поэтому менеджеры памяти существуют и в dll и в exe, поэтому там принципиально нельзя освобождать память выделенную в другом модуле, используя встроенный менеджер памяти. Правда там его тоже можно достадочно легко подменить и сделать его разделяемым.

А вообще, идейно это не правильно. Память должна освобождаться там же, где и была выделенна.

Автор: mr.DUDA 17.4.2004, 10:10
SMILic, я конечно рад помочь, но:
1) для этого вовсе не обязательно поднимать на форуме тему, созданную почти год назад, существует такая вещь как ПМ
2) по "паскалю" помогут товарищи, сидящие на форуме по Delphi

Fantasist, в целом согласен, но вот какая фигня: создаётся ли при линковке DLL отдельный блок функций CRT, или используется тот, что и в EXE, подгрузившей данную DLL ?... В общем-то, суть оригинального вопроса была и не в этом, а в том, что когда DLL выгружается - соответственно все функции, в т.ч. и виртуальные методы классов - становятся недоступны, отчего генерируется исключение в случае вызова виртуального деструктора объекта, динамически созданного в DLL.

Думаю, что на этом можно тему и закрыть, всем спасибо за ответы.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)