Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.01.11;
Скачать: CL | DM;

Вниз

TIBataBase и DLL   Найти похожие ветки 

 
Maxick ©   (2008-03-13 08:55) [0]

Проблема следующего характера: Передовая в ДЛЛ данный объект и поимел проблему: при завершении приложения в главной форме не могу фрикнуть (DB.Free) объект DB=TIBDataBase. Вызывается исключение: Ошибка опирации с указателем. Соответственно, если мне не всвобождать DB (я ее создаю сам), то исключение: "приложение ххх.exe обратилось к адрессу хххх" и т.д.
Собственно вопрос: с чем это связано и как с тим бороться? Варианты типа "обработай сам это исключение" не хотелось бы слюшать.


 
IntruderLab   (2008-03-13 09:05) [1]

как вариант используй CoInitialize() и CoUnInicialize(), ShareMem прописаны в главной форме и в dll


 
Maxick ©   (2008-03-13 10:15) [2]

IntruderLab, Можно будет и попробовать. Я так понимаю, при передачи объекта (указателя) в длл и происходитв вся эта бодяга. В длл у меня форма и работа с базой (таблицы и т.п.). Форма вызывается модально и после высвобождается, но хвост от TIBDataBase остается. Причем, это единственный обект с такой траблой на моей памяти.
Текст в длл:

function xxx(app:TApplication; db: TIBDataBase): boolean; stdcall;
var
 hdll: TApplication;
begin
 hdll:= application;
 application:= app;
 DataBase:= db;  
 fmForm:= TfmForm.Create(Application);
 fmForm.ShowModal;
 fmForm.Free;
 application:= hdll;


Соответственно вызов:

...
DB.Create(self);
...
//тут динамическая загрузка длл
...
xxx(Application,db);
...
//и в событии OnClose главной формы
db.free;

Весь фокус еще в том, что если фрикать в процедуре (OnCreate главной формы), где создавалась db (там же и функцию из длл вызывать) то нет проблем совсем.


 
Maxick ©   (2008-03-13 10:17) [3]

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


 
Сергей М. ©   (2008-03-13 10:24) [4]


> Maxick


http://delphimaster.net/view/1-1205238747/


 
Сергей М. ©   (2008-03-13 10:37) [5]


> и в событии OnClose главной формы
> db.free;


Разве это логично ?

Уж если объект создан тобой сразу после конструирования формы (OnCreate), то и уничтожать его, очевидно, следует непосредственно перед разрушением этой формы (OnDestroy).


> DB.Create(self);


А это что еще за фигня ?
Разве DB у тебя объявлен как TComponentClass ?


 
Maxick ©   (2008-03-13 11:03) [6]


> Сергей М. ©   (13.03.08 10:37) [5]


Я так понял, вы про это:
"1. В исх.кодах своих exe- и dll-проектов убираешь все касаемое параметра Appl, т.е. передача этого параметра не нужна вообще.

2. Во всех своих проектах устанавливаешь крыжик
Project->Options..->Packages->Build With Run-Time Packages
и после этого полностью ребилдишь эти проекты.

Все !! Больше никаких телодвижений делать не нужно."
Прав?
А про Крейт - дошло :). А про дестрой - пробовал - неканает.


 
Сергей М. ©   (2008-03-13 11:05) [7]


> Прав?


Да.


> про дестрой - пробовал - неканает


Это же не редиска, чтобы "канать")


 
Maxick ©   (2008-03-13 11:09) [8]

Ладно, сейчас исходников рядом нет (нахожусь в другом месте, долеко от того компа, где все это делается), попробую - отпишусь.


 
Maxick ©   (2008-03-13 11:17) [9]


> Сергей М. ©

Но всеравно не совсем въезжаю - я передаю в длл Application а не ее Handle, т.е. длл полностью привязываю к смоему аплу... Т.о., как здесь: "У твоей dll св-во MainForm объекта Application равно nil.
Удивись, почеши репу, сделай выводы)" - не соответствует моему случаю. И с чаилдами у меня проблем никогда небыло... уже давно все в длл спихиваю, ну нравится мне так - легче в отладке больших проектов, а также в абгрейдах (патчах) у клиентов.
Или я что-то не допонимаю? ;)


 
Сергей М. ©   (2008-03-13 11:33) [10]


> Или я что-то не допонимаю?


Именно.

Выполнение указанных в [4] рекомендаций приведет к тому, что у всех взаимодействующих модулей в составе приложения будут едиными (общими) объекты Application и Screen (и еще много чего).

Суть проста - сборка всех взаимодействующих проектов с упомянутой опцией ведет к использованию ими одного и того же экз-ра пакета vclxx.bpl (и, самое главное, пакета rtlxx.bpl), в котором "живут" такие (весьма важные в дан.случае) глобальные объекты как Application и Screen.


 
Maxick ©   (2008-03-13 12:16) [11]

Суть понял. Но если, ради интереса, попробовать передавать в DLL помимо Application еще и Screen? Каков будет результат в моем случае? (незнаю почему, точнее не помню, но Screen я довно перестал передавать в ДЛЛ - видимо неувидел в этом нужды... года 3 тому назад было...)


 
Сергей М. ©   (2008-03-13 12:24) [12]


> еще и Screen? Каков будет результат в моем случае?


Screen не имеет к твоей проблеме никакого отношения.


 
Maxick ©   (2008-03-13 12:36) [13]

Значит получается проблема именно в экземплярах (копиях) в памяти процесов. Извините за мою докапываемость, но я хочу понять именно причину. Т.о. смогу не допускать подобных ситуаций в своих прогах. Да и поняв причину - метод решения проблемы становится очевидным.


 
Сергей М. ©   (2008-03-13 13:05) [14]


> проблема именно в экземплярах (копиях) в памяти процесов


Ну говоря упрощенно - да.


 
Maxick ©   (2008-03-13 13:26) [15]

и решение, получается, только одно - исключить размножения экземпляров Application (даже передовая и присваивая Application в ДЛЛ он есть свой). Предлагаемый Вами метод, при создании экземпляра ДЛЛ экзешником не создает отдельный Апл а присваевает ему от ехе, чем исключаются все подобные проблемы. И это единственный выход из данной ситуации. Я все правильно понял? Спасибо вам за помощь. Буду пробовать, в случае неудачи напишу.


 
Maxick ©   (2008-03-13 19:04) [16]


> Сергей М. ©

Большое спасибо еще раз, все чудесно заработало без ошибок... пока... дальше посмотрим ;)


 
Maxick ©   (2008-03-13 19:45) [17]


> Сергей М. ©

НЕ все протестив дал я предыдущий ответ!
Оно заработало,т.е. там где были траблы (не меняя код) ушли. Убирая в ДЛЛ аппликашион настает кирдык функции (приложение хххх обратилось по адресу 000000 к.... 00000), при попытке фрикаль "DB" (перенЁс в Он Дестрой) таже бадяжка (приложение ххх обратилось по адресу 00000...). И самое прикольное, можно не фрикать и тогда все функции работают (без убирания в длл апла), но там где (в [2] последняя строка) все чудненько работало - перестало напрочь... пока еще я не проверял/выяснял/эксперементировал - но результат не совсем тот, к которому я готовился. тоесть, при убирании в длл апла (Application, т.е его передачу в ДЛЛ) - DLL не понимает крейта формы...


 
Игорь Шевченко ©   (2008-03-13 23:29) [18]


> при убирании в длл апла (Application, т.е его передачу в
> ДЛЛ) - DLL не понимает крейта формы...


Сам понял чего написал - дай другим понять.


 
Германн ©   (2008-03-14 00:40) [19]


> Сам понял чего написал - дай другим понять.
>

При таком французском ("аппликашион настает кирдык", "при попытке фрикаль "DB"", "таже бадяжка", "можно не фрикать", "без убирания в длл апла")  лучше не надо. Не дай бог мозги расплавятся при попытке понять.


 
Maxick ©   (2008-03-14 08:56) [20]

Поясню (извините госпада, могу и литературным языком выражаться, если непонятно русскими словами английское когда написано.. :) ):

> > при убирании в длл апла (Application, т.е его передачу
> в
> > ДЛЛ) - DLL не понимает крейта формы...
>
>
> Сам понял чего написал - дай другим понять

В DLL было:
function xxx(apl:TApplication; DB: TIBDataBase): boolean; stdcall;
В DLL стало:
function xxx(apl:TApplication; DB: TIBDataBase): boolean; stdcall;
Подчеркнутое и есть в написаном в [17] "апл".
Вызов в ЕХЕ соответственно тоже исправлен. Т.о. я убрал упоминания в DLL об Application, как рекомендовано в [6]. После чего вызов функции из DLL стал невозможен.
Но если не убирать передачу Application в DLL (xxx(Aplication,DB);), то фукция вызывается безпроблем.
Также в событии OnDestroy высвобождение объекта TIBDataBase - DB.Free вызывает Exeption.
Сразу поправлю написаное в [2]: Читать не DB.Create(self) а DB:= TIBDataBase.Create(Self).
Надеюсь пояснил всё? Сразу оговорюсь: пока еще я не выяснял, что я сделал не так, т.к. вчера был уже поздний час, и большая усталость. :)
Если подталкнете в нужном направлении - буду очень признателен!


 
Maxick ©   (2008-03-14 08:57) [21]

Извините, в DLL Стало
function xxx(DB: TIBDataBase): boolean; stdcall;


 
Сергей М. ©   (2008-03-14 10:30) [22]


> Maxick ©   (14.03.08 08:57) [21]
>
> в DLL Стало


Показывай еще как "стало" в ехе - прототип, строка вызова ..


 
Maxick ©   (2008-03-14 11:44) [23]

В ехе:

...OnCreate(Sender...);
...
db:= TIBDataBase.Create(Self);
...
end; //end OnCreate
...
Procedure....
type
TFunc = function(db:TIBDataBase):boolean;stdcall;
var
xxx: TFunc;
hdll: THandle;
begin
...
hdll:=LoadLibrary("zzz.dll");
@xxx:= GetProcessAddress(hdll,"xxx");
if xxx(DB)
then ...
else begin
db.free; //Здесь программа обращается по адрессу 0000...
freeLibrary(hdll);
Applikation.Terminate;
exit;
end; //if else
freelibrary(hdll);
end;
...
procedure ...OnDestroy(Sender...);
...
db.Free;

Естественно я сейчас не копирую с исходников а по памяти и выкидывая имена и всякий ненужный в данном случае код.


 
Сергей М. ©   (2008-03-14 11:52) [24]

Значит проблема в потрохах самой ф-ции xxx


 
Maxick ©   (2008-03-14 12:16) [25]

потраха примерно выглядят так:

function xxx(db: TIBDataBase): boolean; stdcall;
begin
DataBase:= db;  
fmForm:= TfmForm.Create(Application);
fmForm.ShowModal;
Result:= var1;//результат принимает значение зависимое от события на форме перед закрытием ее
fmForm.Free;

//В самой форме
tbTable:= TIBTable.Create(Self);
whith tbTable do
//Здесь я присваиваю ей Базу данных, транзакцию, датасет, имя таблицы
...
//операции с таблицей, в частности работа с блоб полями через потоки (TStream), и их высвобождение
...
tbTable.Free;
trTransaction.Free;
DataBase:= nil;//пробовал и без этого но просто DataBase.Free делать нельзя!
DataBase.Free //верхнее пояснение и сюда же


 
Сергей М. ©   (2008-03-14 12:19) [26]


> DataBase:= nil;//пробовал и без этого но просто DataBase.
> Free делать нельзя!
> DataBase.Free //верхнее пояснение и сюда же


Убирай нафих и то и другое.


 
Maxick ©   (2008-03-14 12:29) [27]

да это я ради эксперемента ставил, но никаких изменений не увидел. А вот ести оставить DataBase.Free то заново придется в exe с DB колупаться (DataBaseName, Open и т.п.). По этому не использую. Вот только и с этими строками и без них вчера пробовал - разницы нуль.


 
Сергей М. ©   (2008-03-14 12:32) [28]


> и с этими строками и без них вчера пробовал - разницы нуль


Ну тогда продолжай "колупаться", если "разницы нуль")


 
Maxick ©   (2008-03-14 12:40) [29]

вот здесь не соглашусь, если выполнить DataBase.Free то придется "колупаться", а если DataBase:= Nil то (покрайней мере проверял до выполнения рекомендаций [4]) в exe компонент DB остается нетронутым (не высвобожденым, с conection = true;).
Ну это ладно, уберу эти строки. Но я не думаю что в этом проблема,т.к. я использую подобным образом далеко не одну DLL, и эти строки только в одной, а не работают все (которые с формами и используют TIBDataBase) функции из DLLок.


 
Maxick ©   (2008-03-14 12:41) [30]


> Но я не думаю что в этом проблема

точнее НЕ в этом :)


 
Сергей М. ©   (2008-03-14 12:48) [31]


> Maxick ©   (14.03.08 12:40) [29]


> если выполнить DataBase.Free то


.. то нефих делать это повторно, как это делаешь ты в своем ехе (смотри свои страдания с "фриканьем")

Убийство единожды убиенного карается AV-исключением, что ты и имел "удовольствие" прочувтсвовать)


 
Maxick ©   (2008-03-14 12:54) [32]

> Сергей М. ©   (14.03.08 12:48) [31]

Я понимаю, что речь идет о

> db.free; //Здесь программа обращается по адрессу 0000...
>
> freeLibrary(hdll);
> Applikation.Terminate;
> exit;
> end; //if else
> freelibrary(hdll);
> end;
> ...
> procedure ...OnDestroy(Sender...);
> ...
> db.Free;


?
Ведь в тексте не просто так я дописал:
> db.free; //Здесь программа обращается по адрессу 0000...
и это еще долеко до OnDestroy.
Когда я писал тот фрагмент сразу подумал, что так и поймете о том, что два раза пытаюсь выполнить Free, но я вас огарчу, в тексте идет: if DB<>nil then DB.Free
Может и не совсем коректно, но до тута программа всеравно не добирается...


 
Сергей М. ©   (2008-03-14 13:04) [33]


> два раза пытаюсь выполнить Free


А так оно и есть на самом деле)

И dll тут вообще ни причем - теми же гряблями ты получишь по тому же лбу, где бы ни находилась ф-ция xxx.


> но я вас огарчу, в тексте идет: if DB<>nil


Я не вижу подобной проверки в твоем тексте.

А даже если бы она и была, то для успешной работы возложенной на эту проверку логики ты обязан обNILить указатель при первом же уничтожении объекта, на который этот указатель ссылается.

Да и нафих, спрашивается, уничтожать в dll этот объект, если dll не вправе распоряжаться его жизнью, хотя бы по причине того, что объект этот был передан в dll из создавшего его exe во временное пользование ?

А если так хочится приложить в dll свои шаловливые ручки к уничтожению объекта, то и создавать его изволь в той же dll !


 
Maxick ©   (2008-03-14 13:04) [34]


> Сергей М. ©

У меня появилась мысль, что я сделал не так... через пару часов проверю, а то может зря почем раздую проблему..


 
DrPass ©   (2008-03-14 15:37) [35]


> У меня появилась мысль, что я сделал не так... через пару
> часов проверю, а то может зря почем раздую проблему..

У меня тоже. Ты ж передаешь компоненту в библиотеку. uses ShareMem в dpr-файлах приложения и библиотеки написать не забыл?


 
Сергей М. ©   (2008-03-14 15:39) [36]


> DrPass ©   (14.03.08 15:37) [35]


За каким лешим ему ШароМем, если он последовал (якобы) рекомендации в [4] ?


 
DrPass ©   (2008-03-14 16:11) [37]


> За каким лешим ему ШароМем, если он последовал (якобы) рекомендации
> в [4] ?

Ну здрасьте. Он же передает TIBDatabase, не так ли? Не знаю, что там за рекомендации в [4], перечитывать весь тот тред неохота, но передача компоненты параметром в DLL - это уже фактически означает необходимость использования "межмодульного" менеджера памяти.


 
Сергей М. ©   (2008-03-14 16:15) [38]


> передача компоненты параметром в DLL - это уже фактически
> означает необходимость использования "межмодульного" менеджера
> памяти


Вовсе не обязательно.
Все зависит от конкретной ситуации.
Но если общий менеджер таки необходим, то BwRTP как раз и организует его (и много чего еще кроме оного)


 
Maxick ©   (2008-03-17 05:59) [39]

Нашел я свою ошибку. Дело было вовсе не в DB.Free. У меня в некоторых DLL были не модальные вызовы форм, так вот для этого у меня были initdll и donedll. В InitDll было Form1:= TForm1.Create(Application), а в DoneDll: Form1.Free. Вот  DoneDll и вызывало ошибку: "..обратилась по адресу 0000...". Убрав DoneDll все стало работать.


 
Сергей М. ©   (2008-03-17 08:26) [40]


> а в DoneDll: Form1.Free


> Убрав DoneDll все стало работать


Те же фаберже, только вид сбоку - где-то присутствует попытка повторного уничтожения объекта, только в д.сл. этим объектом является объект-форма.



Страницы: 1 2 вся ветка

Текущий архив: 2009.01.11;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.019 c
15-1226484126
тимохов
2008-11-12 13:02
2009.01.11
Посоветуйте по Apache


6-1196964272
BlazeMaster
2007-12-06 21:04
2009.01.11
Вопрос о компоненте WebBrowser


15-1226927615
-=LeXX=-
2008-11-17 16:13
2009.01.11
Трансятор


11-1196634700
Koss (345-824-826)
2007-12-03 01:31
2009.01.11
Lazarus for WinCe как востоновить окно ???


15-1226819908
dimmy
2008-11-16 10:18
2009.01.11
Console-like control