Проблема с RtlValidateHeap

У меня есть DLL Windows, который в какой-то момент возвращает указатель на класс, который был новичком в коде DLL. Сам класс является очень тонкой оболочкой вокруг другого класса, доступного для DLL.

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

Причины ошибки имеют смысл, exe пытается освободить память в куче DLL, что обычно плохо.

Я придумал несколько возможных решений:

  • Переопределите новый оператор класса, чтобы выделить его память из кучи исполняемого файла (при условии, что я могу даже попасть в это кучное пространство). Обертка очень тонкая, поэтому я бы выделил несколько байтов из кучи exe.
  • Обеспечьте специальную функцию уничтожения для этого класса (yuck).
  • Попросите пользователя не уничтожать класс и жить с утечками (нет!)

Есть ли «нормальный» способ сделать это?

c++,dll,

3

Ответов: 7


3

Большинство библиотек, которые используют такую ??функциональность, будь то C или C ++, действительно идут со своей второй опцией - конкретные функции для получения и выпуска объектов. Это позволяет распределять двоичные DLL, которые не должны быть скомпилированы идентично вызывающему исполняемому файлу.


3

Я видел это поведение, когда один из двоичных файлов был создан с параметрами отладки (в котором используется отладочная куча, которая, помимо прочего, использует RtlValidateHeap), а другой двоичный файл был создан как двоичный файл release. Возможно, стоит проверить, что вы используете только как ...


2

Самым простым решением является (для пользователей Visual Studio) использовать / MD или / MDd везде. Если сам CRT находится в DLL, есть только одна куча. Ваше приложение и ваша DLL поделится им.


1

Вы загружаете DLL динамически во время выполнения (вызывая LoadLibrary) или ссылаетесь на использование .lib-файла во время фазы ссылки на ваш exe? Если вы динамически загружаете / выгружаете DLL, то при удалении DLL все еще загружается? Это классическая проблема для конструкций плагинов, и типичное решение - это что-то вроде ваших вторых специальных функций для создания и удаления объектов, о которых идет речь.


1

Вариант 2 довольно нормальный, например, метод Release (), который просто «удаляет это».

Обратите внимание, что обычно DLL не имеет собственной кучи как таковой - большинство DLL будут делиться кучей процессов (см. GetProcessHeap), но часто среда выполнения языка будет украшать или добавлять прописку вокруг выделенной памяти - так что указатель, на котором заканчивается ваша dll, - это не тот же указатель, который куча будет ожидать в свободном вызове.

Общее правило всегда освобождает выделенную память с помощью свободной функции, изнутри того же модуля.

Однако есть некоторые исключения - память, которую вы знаете, была выделена непосредственно с HeapAlloc из известной кучи, может быть освобождена от другого модуля. GlobalAlloc / GlobalFree работает через модули. Строки, выделенные SysAllocString, могут быть освобождены от другого модуля. Память, которую вы знаете, была выделена той же DLL-версией среды выполнения, может быть освобождена от другого модуля, но я бы держался подальше от этого.

C ++, DLL,
Похожие вопросы
Яндекс.Метрика