delphi应用程序通讯偶尔地结束崩溃 – 供应商责备我的delphi应用程序

我已经写了一个Delphi DLL,通过COM与第三方程序进行通信。 有些用户报告说第三方程序偶尔崩溃。 其他人以相同的方式使用软件从未遇到过崩溃。 发生这种崩溃时,第三方程序似乎只是在我的DLL应用程序中变得不可用。

供应商发誓,Delphi DLL的编码是一个问题,虽然他们没有看到源代码,也不知道DLL是如何导致崩溃的,但是他们知道这是“某种东西”。

除了我相信第三方程序不会由于我的DLL中的一些小问题而崩溃,我们假设在我的DLL中有一些东西需要修复。

我怎样才能确定我的应用程序可能导致这个? 有没有人有通过COM与这样的高敏感程序通信的经验? 有没有一些常见的东西可能会崩溃的第三方程序?

  1. 让顾客开心。
  2. 不要以为这不是你的DLL,它可能是。 即使“ 以同样的方式使用软件的其他人从来没有经历过崩溃 ”,也可能是因为数据不同,它会做不同的事情…
  3. 我建议你在“特殊”诊断版本中设置日志记录到文本文件。
  4. 记录一切,你的参数,你的例外,以及你正在经历的步骤。 也许甚至每个功能的开始和结束,以及其他每一行。

以下是它的样子

Loaded DLL Started MyFunction1 with parameters: 1,4,hello 1 2 ... 500 Ended MyFunction1 

为了使,我会设置一些功能(在他们自己的单位):

 // opens a text file (fixed name), and appends to it. function InitializeLog; // closes the file function CloseLog; //add a log line. function Log(message:string='', startNewFunction:boolean:False); 

你会这样称呼它:

 function MyFunction1(Integer,Integer,String); begin try Log('Loaded DLL'); //use inttostr and do some string concats to get the params Log('Started MyFunction1 with parameters: 1,4,hello',true); //Then every other line: Log; //this would increment a global variable FuncLine:Integer //and write it to the file. except On E:Exception (Log('***'+E.Message)); end; end; 

像这样的应该有一个{$ DEFINE}来启用这些日志功能,以启用/禁用诊断日志记录。

这也可能是有用的。

质量中心查看报告58409。

这是关于FPU Mask和Dll的。

简而言之:

FPU掩码的设置决定如何处理浮点异常。

例如,如果您有一个加载Dll_A(由其他编码)和Dll_B(由您编码)的Applicaion_A(由其他编码),并且您的Dll更改了FPU掩码,则此更改对于Application_A和Dll_A也是有效的。

举个例子:你已经安装了例如WinZIP,SubVersion等,它在Windows文件管理器(右键单击弹出菜单)中注册了附加功能,现在你可以从你的application.exe中调用TOpenDialog,然后这个附加功能可能妥协你的FPU设置。

希望这可以帮助。 (附加提示:以Sysinternal来查看你的应用程序加载了哪些dll)

你有没有考虑过使用MadExcept ? 如果在接口方法中发现错误,则可以记录调用堆栈或向用户显示对话框,并将标准EOleSysError返回给调用exe。

像这样的东西:

  except on e: Exception do begin MadExcept.HandleException(); raise EOleSysError.Create('InitializeObject Failed', ErrorNumberToHResult(1 + CODE_BASE), 1); end; 

如果应用程序挂起但不是抛出异常,则可以使用MadExcept实用程序madTraceProcess来查看发生了什么。 这将让你为正在运行的应用程序生成一个调用堆栈。 你的DLL不会在主线程,但你将能够看到你的调用堆栈。 这是一个很好的方法来告诉你的DLL是否真的在挂起时发生任何事情。

我有一个COM DLL,与不使用MadExcept的EXE交互,这种方法对我来说工作得很好。

如果他们的程序在使用他们发布的界面时崩溃了,我很确定它有什么问题。 证明这是另一回事。

你可以用一个小的Delphi应用程序可靠地复制问题,你可以给供应商? 看到一个可重复的失败可能有助于说服他们,他们需要做一个修复。 至少,它可以帮助确定他们认为自己在做什么“错误”,并告诉你如何做到“正确”。

您也可以尝试使用C#甚至VBScript来复制失败。

如果我正确地理解了这种情况,那么不幸的是,如果你的DLL没有崩溃,被叫的第三方程序停止响应,那么你可以做的事情就不多了。 崩溃是在他们的代码中,但只能由您的DLL调用它触发。 调试日志应该真的在他们的应用程序中完成。
你可以做的事情是记录所有的DLL调用这个参数和一些上下文信息的第三方程序的调用。
然后在崩溃之前查看最后一个痕迹可能会给你一些信息…

我不知道如何madExcept等工作,但我使用jcldebug.pas + JclHookExcept.pas(从JEDI JCL库)很多。 它使Windows API挂钩,所以它捕获所有(!)异常,即使你做了这样的事情:

 try raise exception.create('test'); except //eat exception end; 

通常情况下,你看不到这个异常,因为它被“吃掉”了……但是随着钩子,你会得到所有的异常。 例如:我曾经在Midas.dll中遇到过“灾难性的失败”,通过钩子,我发现在这个异常之前dll中有一个“数据库连接丢失”的错误,所以我知道发生了什么事情。 (btw:JclHookExcept.pas = hook,jclDebug.pas = strack trace)。

我现在看到,JclHookExcept.pas也有一个“JclHookExceptionsInmodulee”过程,所以你可以强制(?)钩住特定库中的所有异常…

一些演示代码:

 procedure AnyExceptionNotify(ExceptObj: TObject; ExceptAddr: Pointer; OSException: Boolean); begin //log exception end; initialization // Start Exception tracking JclStartExceptionTracking; JclTrackExceptionsFromLibraries; JclStackTrackingOptions := [stStack, stRawMode, stAllmodulees]; // Assign notification procedure for hooked RaiseException API call. This // allows being notified of any exception JclAddExceptNotifier(AnyExceptionNotify);