![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Не закрывается приложение при работе с DLL [D7, WinXP]
Norfolk © (2005-10-04 22:43:00)Уважаемые Мастера.
Имеется приложение, которое вызывает форму из DLL. Всё работает как надо, форма из библиотеки вызывается, но когда форма заканчивает работать программа не закрывается, возникает ошибка, что-то вроде Приложение обратилось к памяти по адресу ...(адрес).... Память не может быть "Read". Нажмите ОК для завершения приложения.Такая ошибка возникает только если форма в библиотеке хоть немного сложная и насыщеная элементами. Если же форма в DLL пустая или на ней всего пару кнопок - то всё нормально, всё закрывается и работает.
GrayFace (2005-10-06 14:30:00) [1]evvcom © (06.10.05 11:06) [12]
А уж что там manifest делает, без анализа не скажу, а заниматься этим нет ни времени, ни желания.
Он ничего не делает. Только подключает соответствующий ресурс. Все что делается, делается в модулях UxTheme, Themes и в модулях, их использующих. Возможно, еще где-то.
Bel (2005-10-06 14:14:00) [2]> GanibalLector © (05.10.05 02:38) [3]
> procedure ShowMyForm(Handle:HWND);stdcall;
> var Frm:TForm;
> begin
> Application.Handle:=Handle;
> Frm:=TForm1.Create(Application);
> try
> Frm.ShowModal;
> finally
> Frm.Release;
> Frm.Free;
> end;
> end;
1. Release здесь совершенно ни к чему, в нем (вернее в сообщении, которое этот метод посылает) уже содержится Free.
2. Перед выходом надо вернуть Application.Handle на место.
PS. Это на случай если автор решит воспользоваться этим кодом.
evvcom (2005-10-06 11:06:00) [3]
> Babay © (06.10.05 09:57) [11]
В примере все гладко. XPManifest не юзал, как-то раз попробовал и забыл. Пока и так устраивает. А уж что там manifest делает, без анализа не скажу, а заниматься этим нет ни времени, ни желания.
Я похоже погорячился, адресовав [10] к [9], но в [7] явно кривой подход.
Babay (2005-10-06 09:57:00) [4]То evvcom ©
Поясняю (мож я неправильно выразился)
Итак создаем новую длл в которой есть одна только форма и StringGrid на ней.
в ней пишем функцию
library myDll;
uses
SysUtils,
Classes,
Udll in 'Udll.pas' {Form1};
{$R *.res}
Procedure ShowForm;
Var F:TForm1;
Begin
f:=Tform1.Create(nil);
f.ShowModal;
f.Free;
end;
exports ShowForm index 1 name 'ShowForm';
begin
end.
Созлаем приложение с одной кнопкой которая вызывает функцию из DLL
procedure ShowForm;external 'myDll.dll';
........
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowForm;
end;
запускаем приложение, жмем кнопку, закрываем форму, выходим. Все Ок.
Добавляем в приложение XPManifest.
запускаем приложение, жмем кнопку, закрываем форму, выходим.
Access violation..... при выходе.
Покажите мне > "чужеродные" типы.
Я соглашусь с Вами если вы устраните эту ошибку не подключая DLL динамически. И незабудьте рассказать как Вы это сделали.
З.Ы. или эта ошибка только у меня и автора сабжа возникает?
Пишу на D7
evvcom (2005-10-06 09:30:00) [5]
> А вот если б Вы Юрий докопались было бы весьма интересно
> Ваше мнение.
А чего тут копать? Кривой подход - кривой результат. Нельзя ссылаться на классы, реализованные в другом модуле, так как это "чужеродные" типы. Это если не используются run-time пакеты.
Babay (2005-10-06 08:37:00) [6]То Юрий Зотов © вы совершенно правы. Ошибка происходит гдето в менеджере ХР стилей в VCL. Как я и говорил докопаться неудалось. Знаний не хватает.Я не большой спец :-), да это и не основная моя работа.
А вот если б Вы Юрий докопались было бы весьма интересно Ваше мнение.
То Norfolk © у Вас статическое подключение библиотеки, вам нужно сделать динамическое, то есть библиотека должна грузится не вместе с приложением, а когда она необходима. Мне это помогло. Инфы как это делается должно быть в инете много, если не получится пишите сделаю для Вас пример.
Юрий Зотов (2005-10-06 07:56:00) [7]> Norfolk © (05.10.05 22:11) [7]
Похоже, что дело в параметре AOwner (при завершении программы DLL пытается что-то сделать, используя полученную ссылку на этот компонент - а в этот момент он уже уничтожен в EXE).
Norfolk (2005-10-05 22:11:00) [8]
> Очень знакомо, я уже как-то об этом писал, правда сначала
> сам задавал подобный вопрос. Думаю у Вас тоже самое ;-)
>
> А как Вы подключаете DLL? статически или динамически?
> У меня была такая проблема когда используется XPManifest.
> Ошибку так и неудалось выловить больно глубоко закопана.
>
> Лечится ДИНАМИЧЕСКИМ подключением библиотеки.
>
> То GanibalLector
> с тысячей кнопок такой ошибки нет, да и срядом других элементов
> тоже. Вы поробуйте например StringGrid на форму кинуть,
> и не забудьте про XPManifest в приложении. В случае статического
> подключения получите эту ошибку. Если убрать манифест ошибки
> нет.
Библиотека подключается так:
procedure RunEditorForm(AOwner: TComponent);
external 'editor.dll';
...
procedure TSettingsDlg.RunEditTestBtnClick(Sender: TObject);
begin
RunEditorForm(Self);
end;
Babay (2005-10-05 08:01:00) [9]Очень знакомо, я уже как-то об этом писал, правда сначала сам задавал подобный вопрос. Думаю у Вас тоже самое ;-)
А как Вы подключаете DLL? статически или динамически?
У меня была такая проблема когда используется XPManifest. Ошибку так и неудалось выловить больно глубоко закопана.
Лечится ДИНАМИЧЕСКИМ подключением библиотеки.
То GanibalLector
с тысячей кнопок такой ошибки нет, да и срядом других элементов тоже. Вы поробуйте например StringGrid на форму кинуть, и не забудьте про XPManifest в приложении. В случае статического подключения получите эту ошибку. Если убрать манифест ошибки нет.
GanibalLector (2005-10-05 02:43:00) [10]2 Delphi_is_cool © (05.10.05 00:46) [2]
>Подключен ли модуль ShareMem ?
В комментарии указывается на необходимость вставить ссылку на модуль ShareMem, если библиотека экспортирует длинные строки в параметрах обращения к подпрограммам или как результат функций. При чем тут вызов форм???
GanibalLector (2005-10-05 02:40:00) [11]З.Ы. Писал ночью,так что не судите строго. Одно скажу, MemProf сказал что утечек НЕТ. :))
GanibalLector (2005-10-05 02:38:00) [12]2 Norfolk © (04.10.05 22:43)
Тысяча элементов тебя устроит???
DLL :
library Project1;
uses
SysUtils,
Classes,
Unit1 in 'Unit1.pas' {Form1};
Exports
ShowMyForm;
{$R *.RES}
begin
end.
\\\\\\\\\\\\\\\
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
private
public
procedure CClick(Sender: TObject);
end;
procedure ShowMyForm(Handle:HWND);stdcall;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure ShowMyForm(Handle:HWND);stdcall;
var Frm:TForm;
begin
Application.Handle:=Handle;
Frm:=TForm1.Create(Application);
try
Frm.ShowModal;
finally
Frm.Release;
Frm.Free;
end;
end;
procedure TForm1.CClick(Sender: TObject);
begin
ModalResult:=MrOk;
end;
procedure TForm1.FormCreate(Sender: TObject);
var i:Integer;
h:TButton;
begin
Randomize;
for i:=1 to 1000 do
begin
h:=TButton.Create(Self);
h.Parent:=Self;
h.Top:= Random(Self.Top);
h.Left:=Random(Self.Left);
h.Caption:='MyButton'+IntToStr(I);
h.OnClick:=CClick;
end;
end;
end.
Вызов библиотеки :
const DLLName='Project1.dll';
procedure TForm1.Button1Click(Sender: TObject);
var h:THandle;
ShowMyForm:procedure(Handle:HWND);stdcall;
begin
h:=LoadLibrary(DLLName);
if h>0 then
begin
ShowMyForm:=GetProcAddress(h,PChar('ShowMyForm'));
if Assigned(ShowMyForm) then
ShowMyForm(Application.Handle);
FreeLibrary(h);
end;
end;
Delphi_is_cool (2005-10-05 00:46:00) [13]Подключен ли модуль ShareMem?
Если нет, то его нужно подключить в Dll'ке и в самом проекте(Project->View Source)
ps
Лчуше вместо модуля ShareMem использовать модуль FastShareMem(его можно найти в интернете).
Германн (2005-10-05 00:30:00) [14]А стоило ли пихать форму в DLL?
Столько уже истрачено черных пикселей на слова о "кривости" данного подхода.