/*
Насколько я понимаю, процесс Windows, который загружает одну или несколько библиотек динамических ссылок (DLL) в его адресное пространство, будет разделять это адресное пространство со всеми загруженными DLL - это означает, что эти DLL могут читать и записывать в любую память в адресном пространстве процессов. Однако, когда объекты распределены в куче, каждый модуль (будь то .exe
или одна из загруженных DLL процессов) выделяет из своей собственной кучи. По этой причине крайне важно освободить память от той же кучи, которая выполняла выделение.Проблема очистки кучи выделенных ресурсов через границу модуля DLL Windows
Это все имеет смысл для меня, и я подумал, что могу использовать std::unique_ptr
, чтобы помочь организовать все. Это подход, который я использовал. (Я не имею мой компилятор под рукой в данный момент, но я думаю, что эти фрагменты кода/псевдо-код будет достаточно ясно выразить свои намерения:
*/
Library.h
class ILibrary
{
public:
virtual void DoStuff() = 0;
};
struct Deleter
{
void operator()(ILibrary *p)
{
delete p;
}
};
typedef std::unique_ptr<ILibrary, Deleter> Ptr;
//*MyLibrary.dll*
//Includes Library.h
//Exports:
void GetMyLibrary(Ptr & library)
{
library = Ptr(new MyLibrary); // point (1)
}
//**Program.exe**
//Includes Library.h
//Imports MyLibrary.dll (GetMyLibrary export)
int main()
{
Ptr local;
MyLibrary->GetMyLibrary(local);
local->DoStuff();
} // heap corruption on cleanup
Вы может видеть, что и моя библиотека, и основная программа используют один и тот же заголовок Library.h. Я создаю переменную local
, чтобы удерживать указатель на мою библиотеку. Метод GetMyLibrary (вызывается в DLL) выделяет и назначает new unique_ptr
ссылке, Я использовал назначение в «точке 1», потому что я хочу, чтобы Deleter от cont ext DLL, который будет использоваться для очистки, а не Deleter, который был первоначально назначен переменной local
в моей основной программе. Значение, когда локальное выходит из области видимости, я хочу, чтобы его очистка вызывала Deleter DLL, а не тот, который был первоначально назначен ему (т.е. я использовал library = Ptr(new MyLibrary)
вместо library.reset(new MyLibrary)
, потому что я хочу, чтобы Deleter вызывался из контекста DLL)
В любом случае программа работает, за исключением того, что во время очистки, когда локальный unique_ptr
уничтожает, я получаю исключение кучи (в отладке), которое заставляет меня поверить, что я удаляю неправильную кучу (то есть, unique_ptr
не ведет себя так, как я ожидал)
В конечном счете, я решил решить проблему другим способом, который кажется намного более чистым, но мне просто было любопытно, почему подход выше был неудачным?
«** ** куча» - это большая часть вашей проблемы. Что касается Windows, ** ** куча возвращается ['GetProcessHeap'] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa366569 (v = vs.85) .aspx), и что куча _is_ делится между EXE и DLL (отсюда и название «куча процесса»). – MSalters
Спасибо за ссылку, я прочитаю об этом. – charunnera