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

Вниз

Ошибка при освобождении 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 вся ветка

Форум: "WinAPI";
Текущий архив: 2006.07.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.014 c
15-1151066974
Сатир
2006-06-23 16:49
2006.07.23
Тенниска с вентилятором


15-1150966255
Skyle
2006-06-22 12:50
2006.07.23
Требуется программист Delphi на постоянную работу (Новосибирск)


3-1148184412
Аркадий
2006-05-21 08:06
2006.07.23
добавление поля в таблице


1-1150045065
Nikolaich
2006-06-11 20:57
2006.07.23
Как правильно определить дату в дельфи


2-1151873123
Deny20
2006-07-03 00:45
2006.07.23
помогите чем могите разобраться с печатью Курсак горит!!!





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