Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.49 MB
Время: 0.028 c
15-1151048897
MsGuns
2006-06-23 11:48
2006.07.23
Доступ к объектам 1С из Делфи через COM


2-1151942799
J_SABER
2006-07-03 20:06
2006.07.23
RichtextBox


2-1152030910
J_SABER
2006-07-04 20:35
2006.07.23
доступ к файлам в запароленном архиве


3-1147931584
KinnOk
2006-05-18 09:53
2006.07.23
Сохранение или отмена изменений


2-1151698228
Adil
2006-07-01 00:10
2006.07.23
Открыть ParamStr(1) и не загрузить программу заново.