Delphi programming blog
Источник: http://teran.karelia.pro/articles/item_4450.html
 

мозг нуждается в помощи!

Опубликовано 29.12.2010 г. 13:21
Я как новичок в данном деле начал погружаться в мир разработки динамических библиотек (DLL), и буквально сразу же напоролся на какие то невидимые грабли. Мой мозг почему отказывается осознать, что происходит вокруг. Поэтому не могли бы вы оказать посильную помощь, и направить меня в нужном направлении? :)
Проблема такова: Имеется тестовая группа проектов: приложение и библиотека. Приложение имеет только главную форму, при запуске загружает библиотеку, используя LoadLibrary и при закрытии выгружает ее используя полученные дескриптор и FreeLibrary. Данные две функции реализуют увеличение и уменьшение количества ссылок на библиотеку, и когда оно равно нулю система выгружает библиотеку. В общем то все вполне прозрачно и понятно. Теперь есть библиотека, она не экспортирует никаких функций, не содержит никакого исполняемого кода. В библиотеке есть форма. Пустая, опять же без каких либо обработчиков событий и т.п. Если мы запускаем данный код на выполнение, то все нормально. Но допустим я хочу использовать компоненты TMS Advanced String Grid в форме в DLL. Я допустим добавляю грид на форму и все. опять же не добавляя никакого кода. Можно в принципе не кидать грид, а просто в секцию uses добавить юнит AdvGrid. перекомпилируем библиотеку, запускаем приложение - получаем AV. вот это и есть мой вопрос, что мне делать? Обратившись на форум поддержки TMS, мне сказали, что не видят никакой проблемы в использовании компонентов TMS в DLL. И дали ссылку на пример такой реализации. Пример действительно работает, запускаем приложение, жмем кнопку, показывается форма из длл с гридом. Но вот в чем интерес, нажимая на кнопку программа загружает библиотеку, сохраняя декскриптор в локальной библиотеке. Счетчик ссылок становится равным 1. При закрытии главного приложения необходимо закрыть все формы открытые в длл. Для этого вызывается экспортируемая функция CloseAllForms, после чего выгрузить DLL. Но поскольку дескриптор библиотеки при загрузке был локальным, то они снова грузят библиотеку, опять сохраняя локальный дескриптор, вызывают экспортируемую функцию закрытия форм, и освобождают библиотеку. В итоге получаем, что 2 загрузки, и одна выгрузка. Количество ссылок на библиотеку остается равным 1. т.е библиотека не выгружается из памяти. Я прав в этих рассуждениях или нет? Поэтому если эту магическую заметку прочитает пользователь компонентов TMS, расскажите мне пожалуйста, "что же делать как же быть" (с). Ну и вообще любые объясняющие смысл жизни комментарии приветствуются. Тестовая группа проектов
Метки:  dll  |  TMS 

Комментарии

al
29.12.2010 в 16:05
DLL загружена и не выгружалась. Если опять вызвать LoadLibrary винда вернет хендл уже загруженной DLL
ter
29.12.2010 в 16:56
понятно что дескриптор вернет тот же самый. но при этом увеличится количество ссылок на библиотеку в вызывающей процессе.
FreeLibrary это количество уменьшает, и когда равно нулю выгружает библиотеку. Подсчет ссылок я так понимаю ведется для процесса, а не для системы в целом.
FreeLibrary()
Decrements the reference count of the loaded dynamic-link library (DLL). When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid.

Поэтому если несколько раз используется LoadLibrary то необходимо соответствующее количество FreeLibrary(). По крайней мере то же самое вычитал у Архангельского в книжке.
Chaa
30.12.2010 в 09:48
Посмотрите, в каком месте возникает AV.
Для этого при загрузке DLL запомните адрес, по которому она была загружена. Потом запомните адрес AV. Потом добейтесь, чтоб DLL загрузилась по тому же адресу, и посмотрите, что находится по адресу AV.
В самой Delphi есть старинный баг в реализации всплывающих подсказок. Поток HintMouseThread иногда не завершается при выгрузке DLL и поэтому получается, что поток работает, а его код уже выгружен, и происходит AV.
Также баг может быть где-то в TMS.
Артем
31.12.2010 в 01:30
Присоединюсь к предыдущему комментарию. Но проще запустить длл из под дебагера или использовать какую-нибудь систему багрепортинга - они (кроме прочего) умеют показывать стек на момент исключения. Например MadExceptions или EurecaLog.
ter
31.12.2010 в 16:00
дайте мозг в аренду (:
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно