Главная страница
    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.47 MB
Время: 0.012 c
4-1143433776
Ikota
2006-03-27 08:29
2006.07.23
Чтение из сист. памяти


10-1121686228
Mx
2005-07-18 15:30
2006.07.23
Связь объектов с помощью CORBA


15-1151218322
Nic
2006-06-25 10:52
2006.07.23
Какие преимущества даёт компонент TActionList?


4-1144642984
Vad
2006-04-10 08:23
2006.07.23
Меню чужого приложения


2-1151919058
SDF
2006-07-03 13:30
2006.07.23
Сообщение Onмауспокинулконтрол





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский