Вызывает ли утечка памяти при выгрузке DLL утечку в хост-процессе?

StackOverflow https://stackoverflow.com/questions/132242

Вопрос

Рассмотрим этот случай:

dll = LoadDLL()
dll->do()

...
void do() {
    char *a = malloc(1024);
}
...

UnloadDLL(dll);

Будет ли на этом этапе 1 КБ, выделенная при вызове malloc(), снова доступна хост-процессу?DLL статически связана с CRT.

Это было полезно?

Решение

Нет, у тебя не течет.

Если вы смешиваете модели dll (статическую, динамическую), то вы можете получить ошибку памяти, если вы выделяете память в dll, которую вы освобождаете в другой (или освобождаете в exe).

Это означает, что куча, созданная статически связанным CRT, не совпадает с кучей CRT другой dll.

Если бы вы связали динамическую версию CRT, то возникла бы утечка, поскольку куча распределяется между всеми динамически связанными CRT.Это означает, что вы всегда должны проектировать свои приложения с использованием динамических CRT или гарантировать, что вы никогда не управляете памятью за пределами границы dll (т. е. если вы выделяете память в dll, всегда предоставляйте процедуру для ее освобождения в той же самой dll).

Другие советы

  1. Память, используемая процессом, отслеживаемая ОС, применима ко всему процессу, а не только к DLL.

  2. Память предоставляется программе кусками ОС, называемыми кучей.

  3. Менеджеры кучи (malloc/new и т. д.) дополнительно делят куски и передают их запрашивающему коду.

  4. Только когда выделяется новая куча, ОС обнаруживает увеличение памяти.

  5. Когда DLL статически связана с библиотекой времени выполнения C (CRT), частная копия CRT с функциями CRT, которые вызывает код DLL, компилируется и помещается в двоичный файл DLL.Malloc также включен в это число.

  6. Эта частная копия malloc будет вызываться всякий раз, когда код, присутствующий внутри статически связанной DLL, пытается выделить память.

  7. Следовательно, частная куча, видимая только для этой копии malloc, извлекается из ОС этим malloc и распределяет память, запрошенную кодом, внутри этой частной кучи.

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

  9. Однако если DLL динамически скомпонована, память выделяется одной общей версией malloc, глобальной для всего кода, связанного в общем режиме.

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

Изменить — добавлены описания сценария связывания.

Вы не можете сказать.Это зависит от реализации вашей статической и динамической ЭЛТ.Это может зависеть даже от размер распределения, поскольку существуют CRT, которые перенаправляют большие выделения в ОС, но реализуют собственную кучу для небольших выделений.

Проблема с протекающей ЭЛТ, конечно, в том, что она протекает.Проблема с CRT, которая не протекает, заключается в том, что исполняемый файл может разумно рассчитывать на использование памяти, поскольку выделенная память должна оставаться пригодной для использования до тех пор, пока не будет вызвана свободная память.

Из MSDN Потенциальные ошибки при передаче объектов CRT через границы DLL

Каждая копия библиотеки CRT имеет отдельное и отличное состояние.Таким образом, объекты CRT, такие как ручки файлов, переменные среды и локалы, действительны только для копии CRT, где эти объекты выделяются или устанавливаются.Когда DLL и его пользователи используют разные копии библиотеки CRT, вы не можете передать эти объекты CRT через границу DLL и ожидать, что они будут правильно подобраны с другой стороны.

Кроме того, поскольку каждая копия библиотеки CRT имеет свой собственный диспетчер кучи, распределение памяти в одной библиотеке CRT и передача указателя через границу DLL, которая будет освобождена другой копией библиотеки CRT, является потенциальной причиной для повреждения кучи.

Надеюсь это поможет.

На самом деле отмеченный ответ неверен.Вот именно и есть утечка.Хотя технически для каждой библиотеки DLL существует возможность реализовать свою собственную кучу и освободить ее при завершении работы, большинство куч «время выполнения» — статических или динамических — представляют собой оболочки вокруг API кучи процесса Win32.

Если не принять особых мер, чтобы гарантировать, что это не так, dll будет утечка выделения памяти для каждого цикла загрузки, выполнения и выгрузки.

Можно было бы провести тест и посмотреть, есть ли утечки памяти.Вы запускаете простой тест 30 раз, каждый раз выделяя 1 МБ.Вы должны это понять довольно быстро.

Одно можно сказать наверняка.Если вы выделили память в DLL, вам также следует освободить эту память там (в DLL).

Например, у вас должно быть что-то вроде этого (простой, но интуитивно понятный псевдокод):

dll = DllLoad();

ptr = dll->alloc();

dll->free(ptr);

DllUnload(dll);

Это необходимо сделать, поскольку у DLL куча отличается от исходного процесса (который загружает dll).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top