Delphi 中的异常和DLL

g2ieeal7  于 2023-05-28  发布在  其他
关注(0)|答案(5)|浏览(168)

Delphi 中处理DLL内部抛出的异常的正确方法是什么?
就像这样

on E : ESomeException do ...

if (E is ESomeException) then ...

失败,因为DLL和主应用程序的类型注册表是分开的。

dgiusagp

dgiusagp1#

因为纯DLL的异常是不允许跨越DLL边界的(就像Deltics提到的那样)--不管是什么语言。
你得到了all sorts of trouble there,特别是因为你不知道边界两边是哪种语言、RTL、内存管理器等。
因此,您又回到了经典的错误处理范例:

你可以使用BPL包来代替DLL(如Lars所建议的):在那里,你知道双方将使用相同的RTL和内存管理器。
无论如何,包和BPL通常都会给予您带来版本控制的噩梦(太多的自由度)。
一个更严格的解决方案是使用单片可执行文件;这解决了两个问题:

  • 更容易的版本控制
  • 保证只有一个RTL和内存管理器

--杰伦
PS:我把这个作为一个额外的答案,因为这样可以更容易地粘贴链接。

cunj1qz1

cunj1qz12#

最安全的方法是首先不允许异常从DLL中“逃逸”。
但是如果你无法控制DLL的源代码,因此无法确保这一点,你仍然可以测试异常类名:

if SameText(E.ClassName, 'ESomeException') then ...
xt0899hw

xt0899hw3#

如果你为你的应用程序和dll都使用运行时包(至少是rtlxx.bpl),那么两者都有相同的类型,它就能工作。当然这限制了你的dll只能用于 Delphi /BCB。
另一个解决方案是根本不像Deltics建议的那样使用异常。返回错误代码。
或者使用COM。那么你就可以有例外,而不是限制你的dll只限于 Delphi 。

insrf1ej

insrf1ej4#

我认为,大家都同意不应该允许从DLL中逃逸异常。
但有时您无法控制DLL,并且无法避免异常问题。
例如,我们遇到了一个外部DLL中的函数问题,该函数被AV软件设置(“勒索软件保护”)阻止,导致 Delphi 中的访问违规。
下面的代码为我们工作:

var
    O: TObject;
    Msg: AnsiString;   //type depending on DLL
begin
    try
        CallExternalDll(...);
    except
        //on E: Exception do might lead to access violations
        //because the exception might not be of type Exception
        O := ExceptObject;
        //Depending on the DLL this or an other cast might 
        //or might not be necessary:
        Msg := PAnsiChar(Exception(O).Message);

        raise Exception.Create(Msg);
    end;
end;
ukxgm1gy

ukxgm1gy5#

这个解决方案似乎适合我:

function ExceptionMatch (Exc : Exception; ExcClass : TClass) : Boolean;

 var
    CurrClass           : TClass;

  begin
  CurrClass := Exc.ClassType;
  while (CurrClass <> nil) do
    begin
    if SameText (CurrClass.ClassName, ExcClass.ClassName) then
      Exit (True);
    CurrClass := CurrClass.ClassParent;
    end;
  Result := False;
  end;

我已经准备好让你毁了这个:)
这种做法有什么问题?什么是潜在危险?

相关问题