奇怪的是,当我从DLL调用函数时,应用程序无法启动但未发现错误

时间:2012-11-11 11:58:33

标签: delphi delphi-xe2

在我的项目中我有一个Windows应用程序和一个DLL。我写过dll所以:

library MyDLL;

uses
  System.SysUtils,
  System.Classes;

{$R *.res}

function Prova: string; export;
begin
  result := 'prova';
end;

exports Prova;

begin
end.

并且在主程序中我调用了例程:

unit FrmMain;

interface

uses
 // declaration uses // 

function Prova: string; external 'MyDLL.dll';

type    
 // declaration type //

implementation

begin
  ...
  TAdvEdit1.Text := Prova;  // [1] // 
  ...
end;

end.

当我编译所有项目时没有报告错误,并且状态报告SUCCESS,但是应用程序无法启动。 如果我删除行[1],它可以正常工作。通常,当我调用函数Prova时,应用程序无法启动。 我能解决这个问题吗?非常感谢。

2 个答案:

答案 0 :(得分:3)

您描述的行为是您的应用程序无法加载时会发生的行为。从调试器运行时,您会收到静默故障。在没有调试器的情况下运行时,您将看到一条错误消息“应用程序无法初始化...”。这将提供详细信息。

在您的情况下,似乎可能的原因是库加载器无法解析DLL的依赖性。这就是当删除对外部函数的调用时应用程序运行的原因。删除该调用时,还会删除对外部DLL的依赖性。通过确保可以加载DLL来解决问题。例如,将其放在与可执行文件相同的目录中。

调试器的静默失败令人沮丧。一旦你经历了几次,你就会知道该怎么做 - 在没有调试器的情况下运行,找出真正出错的地方。

我还建议您不要跨模块边界传递托管Delphi字符串。这将迫使您对可执行文件和DLL使用相同的编译器。如果您要接受该约束,那么您也可以使用包。正如您的代码所代表的那样,它需要使用ShareMem才能工作。但我不建议这样做。

答案 1 :(得分:2)

您的程序和DLL具有单独的内存管理器。作为一般规则,不应在应用程序内部使用从DLL分配的内存(反之亦然)。 分配来自哪里?在Delphi中,“string”是托管类型,即当您将一些文本分配给字符串变量时(在您的情况下结果:='prova'),Delphi(在场景后面)使用DLL的内存管理器为该字符串分配内存。然后,例如,如果您在主应用程序中分配其他文本值,则重新分配使用应用程序的内存管理器,这是坏的,即应用程序的MM正在触摸它尚未分配的内存。

要解决此问题,您必须在“应用程序(。dpr文件)中包含”SimpleShareMem“(Delphi> = 2010 IIRC?)单元作为您的USES子句的第一个单元。 DLL:

library MyDLL;

uses
  SimpleShareMem, // **MUST BE THE FIRST UNIT**
  System.SysUtils,
  System.Classes;
...


program YourApp;

uses
  SimpleShareMem, // **MUST BE THE FIRST UNIT**
  // declaration uses // 

可以在“Start > Programs > Embarcadero RAD Studio > Samples > Delphi > RTL > SimpleShareMem

中找到此方法的示例

您还可以使用PCHAR在DLL和APP之间传输字符串。