Delphi:在dll中调用过程后访问冲突

时间:2012-09-20 10:31:02

标签: delphi delphi-7

我在dll中创建了一个打开表单然后打印报表的过程。 这个过程完全适用于exe。 我已经将包含此过程的单元和表单包装在一个dll中,并按如下方式导出过程:

{$R *.res}


Procedure PrintTopSellers; stdcall;
begin
  Form1 := TForm1.create(nil);
  GetMonth := TGetMonth.create(nil);
  Form1.PrintTopSellers;
end;


exports PrintTopSellers;

begin
end.

现在我从exe中调用此过程PrintTopSellers,如下所示:

procedure TForm1.Button5Click(Sender: TObject);
type
  TRead_iButton = function :integer;
var
    DLL_Handle: THandle;
    Read_iButton: TRead_iButton;
Begin
    DLL_Handle := LoadLibrary('c:\Catalog.dll');
    if DLL_Handle <> 0 then
    begin
       @Read_iButton:= GetProcAddress(DLL_Handle, 'PrintTopSellers');
        Read_iButton;
    end;
    application.ProcessMessages;
    FreeLibrary(DLL_Handle);

end;

对程序的调用完美无缺。但是,在我关闭调用exe之后,我收到了访问冲突 - “地址00BAC89C的访问冲突。读取地址00BAC89C。”

感谢任何帮助。我使用的是Delphi 7。 感谢

2 个答案:

答案 0 :(得分:6)

您正在DLL中创建一个窗口控件Form1。但你永远不会破坏它。然后卸载DLL,卸载实现DLL创建的所有窗口的窗口过程的代码。大概是当进程关闭时,会调用窗口过程,但不再有代码了。

通过销毁DLL创建的所有对象来解决问题。在PrintTopSellers终止时,我认为最好的方法就是这样做。

Procedure PrintTopSellers; stdcall;
begin
  Form1 := TForm1.create(nil);
  try
    GetMonth := TGetMonth.create(nil);
    try
      Form1.PrintTopSellers;
    finally
      GetMonth.Free;
    end;
  finally
    Form1.Free;
  end;
end;

在加载DLL的代码中,TRead_iButton声明不正确。它应该是

TRead_iButton = procedure; stdcall;

但这实际上并没有解释这里的问题,因为签名不匹配对于无参数的过程是良性的。

答案 1 :(得分:3)

&#34; TRead_iButton = function:integer;寄存器;&#34;

&#34;程序PrintTopSellers; STDCALL;&#34;

绝对不同的约定/类型,不是吗?

让它们变得一样。 更好的沟渠DLL和使用包(BPL),然后编译器将使您免受此类错误


我们也没有在Form1.PrintTopSellers和TGetMonth中看到代码。所有这些都可以在主机exe中留下一些悬空指针,这将在DLL卸载后获得访问权。


准确显示导致AV的函数调用链 - 它被称为堆栈跟踪。 调试信息+一些像Jedi CodeLibrary(由Delphi IDE使用)的excaption中断madExcept,EurekaLog,synopse日志和许多其他存在。

Display the call stack in a Delphi Win32 application


DLL或EXE是否使用运行时包?