Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2009.01.11;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.007 c
2-1227819867
demon
2008-11-28 00:04
2009.01.11
Как сохранить в ini-файл значение HBRUSH ?


2-1227792256
NS1989
2008-11-27 16:24
2009.01.11
Untyped - параметр


2-1227880896
olegIvan
2008-11-28 17:01
2009.01.11
TreeView


15-1226588778
antonn
2008-11-13 18:06
2009.01.11
нужен jpeg.pas


4-1202912615
Андрей Пл
2008-02-13 17:23
2009.01.11
Как определить что данные черех СОМ порт отправлены???





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский