Проблема с Dll
преамбула:
я написал программу, которая поддерживает подключаемые dll модули. Во время тестирования одного только модуля всё работало нормально. Когда модулей стало два и три что-то пошло не так...
амбула:
когда я запускаю функцию сканирования папки plugins на наличие модулей, я получаю неизвестные ошибки в том месте, где заканчивается цикл for и где нет не единой строчки кода. ошибка это страшная - access violation, которая через несколько секунд приводит к такой же ошибке главной ехе`шки, а потом и к abnormal program termination проги.
не могу вычислить ошибку. где она может быть?
p.s.1: если не производить сканирование модулей - они (хоть 5 штук вместе) работают нормально и без ошибок
p.s.2: процесс сканирования заключается в следующем:
а) запускается цикл, равный каоличеству файлов в каталоге plugins
б) из каждого dll вытаскивается информация о нём и о его идентификаторе (два запроса на вызов двух разных функций dll`ки)
в) информация обрабатывается и заносится в таблицу
г) задействуется функция FreeLibrary
д) цикл следует к следующему файлу...
Помогите - скажите, что может вызывать такую неадекватную реакицю?
могите - скажите, что может вызывать такую неадекватную реакицю?
Использование AnsiString и поклание на правила Борланда по созданию DLL. AnsiString может использоваться косвенно, через компоненты.
Использование AnsiString и поклание на правила Борланда по созданию DLL. AnsiString может использоваться косвенно, через компоненты.
Спасибо за совет. AnsiString действительно использовалось у меня в этом проекте повсюду...
У меня два вопроса возникло:
1. что за правила Борланда - где их почитать?
2. Что лучше использовать вместо AnsiString - простой String или char и где прочитать про их особенности?
1. что за правила Борланда - где их почитать?
Не знаю, как в Билдере, а в Дельфи правила пишутся в чистом проекте DLL в комментариях. Предлагают подключить к проекту ShareMem и завязать на шее узел в форме borlandmm.dll.
Можно все оставить как есть. Класть на правила надо тоже уметь.
Например, нигде в анналах Борланда не описан факт, что при компиляции с пакетами менеджер памяти существует в одном экземпляре, поэтому borlandmm.dll на фиг не нужен.
Если компиляция с пакетами невозможна по каким-то причинам, а узел завязывать все-таки не хочется, достаточно экспортировать из DLL дополнительную процедуру, инициализирующую менеджер памяти переданным ей в качестве параметра. На Дельфи это будет выглядеть так:
begin
MemoryManager := Manager;
end;
Тип TMemoryManager и глобальная переменная MemoryManager описаны в System.pas.
Правда, ни Дельфи, ни Билдер, на знают о нашей процедуре инициализации, и при загрузке плагина придется вызывать ее вручную. Ничего не поделаешь - тяжела программисткая доля. Надо принять ее как неизбежное зло.
1. какова максимальная длина текстовой строки в формате char?
2. нужно ли ставить где-нибудь значки типа & или * при использовании char для передачи данных в DLL?
Снова вопросы:
1. и куда эту MemoryManager впихивать?
2. не рекомендуется использовать AnsiString в каком качестве:
а) в качестве return значения функции
б) в качестве аргумента функции?
Просто у меня когда-то прога моя сожержала всего один dll (настройки). Там в обоих случаях была AnsiString и никаких глюков вот уже за полгода не возникало... а в новом проекте (с многими dll) - постоянный access violation если использовать вторую функцию из того же dll в то время, как работает основная функция....
1. и куда эту MemoryManager впихивать?
Реализацию я уже написал.
2. не рекомендуется использовать AnsiString в каком качестве:
а) в качестве return значения функции
б) в качестве аргумента функции?
Не уточнял. На самом деле проблема с AnsiString заключается в том, что они создаются и перераспределяются мало того, что неявно, так еще и в разных местах!
Давай начнем сначала: с пакетами или без пакетов все собирается? Если с пакетами - проблема в другом.
Одновременно - это как? Через потоки выполнения (thread)?
Давай начнем сначала: с пакетами или без пакетов все собирается? Если с пакетами - проблема в другом.
таким образом:
pSF pCallPluginConfig;
HMODULE dllPlugin = LoadLibrary((edt_plugins->Selected->Caption).c_str());
pCallPluginConfig = (pSF)GetProcAddress(dllPlugin, "getSettings");
if (pCallPluginConfig != NULL)
{
pCallPluginConfig(idVersion, "fromSettings");
}
При запуске программы её главный модуль (ехе) запускает подключёенные dll. Этот dll работает на протяжении всего цикла работы проги.
Во время этой работы, например, полез я в настройки (config.dll) и оттуда вызвал другую функцию того dll, который был запущен в начале работы проги.
таким образом:
Я про параметры Linker'а. Используются пакеты (packages) или нет?
Я про параметры Linker'а. Используются пакеты (packages) или нет?
В Borland C++ Builder 1 ещё нет packages (в 3 и 5 уже есть)... Но, в принципе, стоит всё так, чтобы прога могла работать на любом компе без системных или борландовских библиотек...
Слушай, сделал через char - вроде тот критический глюк пропал, но теперь при каждом закрыии окна (вызванного из dll) выдаётся access violation :( правда на работу проги это не влияет. Всё равно не приятно...
AnsiString может использоваться косвенно, через компоненты.
Эть почему? Всегда использую его например так:
ShowMessage(IntToStr(str.Length());
И никогда проблем не возникало. Что должны иметь, то и имеем.
А вот в делфях, как я помню такого сделать нельзя.
AlphaOmega - где вы откопали это убожество, билдер первой версии? Это же кошмар-р-р! Я с ним работал только раз, но мне хватило.
Слушай, сделал через char - вроде тот критический глюк пропал, но теперь при каждом закрыии окна (вызванного из dll) выдаётся access violation
Скорее всего реализовал переполнение буфера :) - распространенная ошибка при работе с массивами типа char.
Каким образом сделал через char? Пример было бы не плохо увидеть, а то это гадание получается, т.к. способов немерянно при желании можно придумать.
Например, если происходит выход за границы массива (строки char), то имеем возможность частично перезаписать исполняемый код программы. Вот тебе и access violation. В Си, как известно ни кто не проверяет, сколько ты элементов в массив пихаешь.
AlphaOmega - где вы откопали это убожество, билдер первой версии? Это же кошмар-р-р! Я с ним работал только раз, но мне хватило.
Я его использую ещё с тех пор, когда только-только вышел 3-ий билдер. И кстати, хочу сказать, он (первый) намного легче и неприхотливей чем остальные. Файлы получаются на килов 100 - 200 меньше, чем у остальных версий. Кроме того, у этой версии НЕТУ ГЛЮКА нарушения доступа при использовании TListView с ресурсом xp.manifest :)
Кстати, второй access violation (после уже использования char) вызывало то, что функции в dll были типа __stdcall - как только я это слово из их инициализации убрал - ошибки прекратились :)
Появилась проблема.
преамбула:
я написал программу, которая поддерживает подключаемые dll модули. Во время тестирования одного только модуля всё работало нормально. Когда модулей стало два и три что-то пошло не так...
амбула:
когда я запускаю функцию сканирования папки plugins на наличие модулей, я получаю неизвестные ошибки в том месте, где заканчивается цикл for и где нет не единой строчки кода. ошибка это страшная - access violation, которая через несколько секунд приводит к такой же ошибке главной ехе`шки, а потом и к abnormal program termination проги.
не могу вычислить ошибку. где она может быть?
p.s.1: если не производить сканирование модулей - они (хоть 5 штук вместе) работают нормально и без ошибок
p.s.2: процесс сканирования заключается в следующем:
а) запускается цикл, равный каоличеству файлов в каталоге plugins
б) из каждого dll вытаскивается информация о нём и о его идентификаторе (два запроса на вызов двух разных функций dll`ки)
в) информация обрабатывается и заносится в таблицу
г) задействуется функция FreeLibrary
д) цикл следует к следующему файлу...
Помогите - скажите, что может вызывать такую неадекватную реакицю?
А если не вызывать FreeLibrary - ошибка тоже появляется?
А если не вызывать FreeLibrary - ошибка тоже появляется?
1. Всё равно появлялась
2. Если память не очищить, то рано или поздно произойдёт что-то типа переполнения буфера и работа проги на этом будет кончена :(
Но сейчас вроде всё решилось (более мение)
а) я перешёл с AnsiString на char*
б) я отказался от __stdcall
в) я добавил проверку на уже активный dll и если он активен - дополнительная та функция не вызывается...