Текущий архив: 2006.07.23;
Скачать: CL | DM;
Вниз
Ошибка при освобождении dll-ки(пример из Тейксеры и Пачеко) Найти похожие ветки
← →
Pojarnik (2006-04-07 21:22) [0]Здравствуйте, мастера!
Пример взят из книги Тейксера и Пачеко по Delphi 5. Суть проблемы: по нажатии кнопки загружается модальная форма из dll-ки. Но когда эту форму закрываю выплывает системная ошибка "Инструкция по адресу "0х00000000" обратилась к памяти по адресу "0х00000000". Память не может быть "read" ".
Подскажите в чем дело, все-таки авторитетная книжка.
Вот исходный код.
Библиотека и модуль с модальной формой:library CalendarLib;
uses
ShareMem,
SysUtils,
Classes,
DLLFrm in "DLLFrm.pas" {DLLForm};
exports
ShowCalendar;
begin
end.unit DLLFrm;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Grids, Calendar;
type
TDLLForm = class(TForm)
calDllCalendar: TCalendar;
procedure calDllCalendarDblClick(Sender: TObject);
end;
{ Declare the export function }
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime; StdCall;
implementation
{$R *.DFM}
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime;
var
DLLForm: TDllForm;
begin
// Copy application handle to DLL"s TApplication object
Application.Handle := AHandle;
DLLForm := TDLLForm.Create(Application);
try
DLLForm.Caption := ACaption;
DLLForm.ShowModal;
Result := DLLForm.calDLLCalendar.CalendarDate; // Pass the date back in Result
finally
DLLForm.Free;
end;
end;
procedure TDLLForm.calDllCalendarDblClick(Sender: TObject);
begin
Close;
end;
Модуль формы exe-шника:unit MainFfm;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
type
{ First, define a procedural data type, this should reflect the
procedure that is exported from the DLL. }
TShowCalendar = function (AHandle: THandle; ACaption: String): TDateTime; StdCall;
{ Create a new exception class to reflect a failed DLL load }
EDLLLoadError = class(Exception);
TMainForm = class(TForm)
lblDate: TLabel;
btnGetCalendar: TButton;
procedure btnGetCalendarClick(Sender: TObject);
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
procedure TMainForm.btnGetCalendarClick(Sender: TObject);
var
LibHandle : THandle;
ShowCalendar: TShowCalendar;
begin
{ Attempt to load the DLL }
LibHandle := LoadLibrary("CALENDARLIB.DLL");
try
{ If the load failed, LibHandle will be zero.
If this occurs, raise an exception. }
if LibHandle = 0 then
raise EDLLLoadError.Create("Unable to Load DLL");
{ If the code makes it here, the DLL loaded successfully, now obtain
the link to the DLL"s exported function so that it can be called. }
@ShowCalendar := GetProcAddress(LibHandle, "ShowCalendar");
{ If the function is imported successfully, then set lblDate.Caption to reflect
the returned date from the function. Otherwise, show the return raise
an exception. }
if not (@ShowCalendar = nil) then
lblDate.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
else
RaiseLastWin32Error;
finally
FreeLibrary(LibHandle); // Unload the DLL.
end;
end;
end.
Кстати, если закомментировать функцию освобождения библиотеки FreeLibrary, все будет нормально, но библиотека не будет удалена из памяти. Все-таки хочется понять природу ошибки.
← →
kaZaNoVa © (2006-04-08 22:42) [1]какая винда?
имхо глюк в FreeLibrary(LibHandle) может быть ... - типа она еще робит а ты её решил выйгрузить, :crazy: винда и ругаецца
← →
kaZaNoVa © (2006-04-08 22:45) [2]Pojarnik (07.04.06 21:22)
Кстати, если закомментировать функцию освобождения библиотеки FreeLibrary, все будет нормально, но библиотека не будет удалена из памяти. Все-таки хочется понять природу ошибки.
ну так комментируй и делофф .. при выгрузке прог она должна выгрцзиться, иммхо
← →
GrayFace © (2006-04-09 09:57) [3]Пример весьма безграмотный.
1) ShareMem не используется, поэтому строки нельзя передавать. Хотя здесь это, похоже, не критично.
2) Загрузка dll-ки на время выполнения одной функции, как правило, не оправдана. Загрузка - штука долгая, а то, что библиотека в памяти находится без дела не страшно - если что, благополучно уйдет в своп.
Надо, например, так:
var ShowCalendar: TShowCalendar;
procedure TMainForm.btnGetCalendarClick(Sender: TObject);
var
LibHandle : THandle;
begin
// Load procedure
if @ShowCalendar=nil then
begin
LibHandle := LoadLibrary("CALENDARLIB.DLL");
if LibHandle = 0 then
raise EDLLLoadError.Create("Unable to Load DLL");
@ShowCalendar := GetProcAddress(LibHandle, "ShowCalendar");
if @ShowCalendar = nil then
RaiseLastWin32Error;
end;
lblDate.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
end;
Если охото, LibHandle можно запомнить и самостоятельно освободить.
Кстати, не забудь у dll-ки изменить базовый адрес (см. Project Options).
← →
fellix (2006-04-09 10:20) [4]
> Pojarnik (07.04.06 21:22)
Возможные варианты:
1. Использовать uses ShareMem и в DLL, и в EXE (см. Delphi Help).
2. В качестве параметров использовать не String, а PChar.
← →
Pojarnik (2006-04-09 23:30) [5]Спасибо за ответы и ценные дополнения.
← →
jack128 © (2006-04-11 01:19) [6]fellix (09.04.06 10:20) [4]
2. В качестве параметров использовать не String, а PChar.
можно и WideString или OleVariant. Память под переменные этих типов выделяется подсистемой COM , так что мемликов быть не должно..
Страницы: 1 вся ветка
Текущий архив: 2006.07.23;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.012 c