Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows Delphi应用程序与偶尔会崩溃的程序通信-供应商指责我的Delphi应用程序_Windows_Performance_Delphi_Debugging_Com - Fatal编程技术网

Windows Delphi应用程序与偶尔会崩溃的程序通信-供应商指责我的Delphi应用程序

Windows Delphi应用程序与偶尔会崩溃的程序通信-供应商指责我的Delphi应用程序,windows,performance,delphi,debugging,com,Windows,Performance,Delphi,Debugging,Com,我已经编写了一个Delphi DLL,它通过COM与第三方程序通信。一些用户报告说,第三方程序偶尔会崩溃。其他以相同方式使用该软件的人从未经历过崩溃。发生此崩溃时,第三方程序在我的DLL应用程序中似乎变得不可用 供应商发誓这是Delphi DLL如何编码的问题,尽管他们没有看到源代码,也不能说出DLL是如何导致崩溃的,但他们知道这是“什么” 除了我认为第三方程序不应该因为我的DLL中的一些小问题而崩溃之外,让我们假设我的DLL中有一些东西需要修复 我如何确定我的应用程序可能导致这种情况?有没有人

我已经编写了一个Delphi DLL,它通过COM与第三方程序通信。一些用户报告说,第三方程序偶尔会崩溃。其他以相同方式使用该软件的人从未经历过崩溃。发生此崩溃时,第三方程序在我的DLL应用程序中似乎变得不可用

供应商发誓这是Delphi DLL如何编码的问题,尽管他们没有看到源代码,也不能说出DLL是如何导致崩溃的,但他们知道这是“什么”

除了我认为第三方程序不应该因为我的DLL中的一些小问题而崩溃之外,让我们假设我的DLL中有一些东西需要修复


我如何确定我的应用程序可能导致这种情况?有没有人有过通过COM与这种超敏感程序通信的经验?是否有一些常见的东西可能会导致第三方程序崩溃?

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

你能用一个小的Delphi应用程序可靠地复制这个问题吗?看到可重现的故障有助于说服他们需要进行修复。至少,这有助于查明他们认为你做得“不对”的地方,并告诉你如何做得“对”

您还可以尝试使用C#甚至VBScript复制故障

  • 让顾客满意
  • 不要以为它不是你的dll,它可能是。即使“其他以相同方式使用该软件的人从未经历过崩溃”,也可能是由于数据不同,它会做不同的事情
  • 我建议您将日志记录设置为“特殊”诊断版本中的文本文件
  • 记录所有内容、参数、异常和正在执行的步骤。甚至可能是每个函数的开始和结束,以及每一行
  • 下面是它的外观

    Loaded DLL
    Started MyFunction1 with parameters: 1,4,hello
       1
       2
       ...
       500
    Ended MyFunction1
    
    为了做到这一点,,,我设置了一些函数(在它们自己的单元中):

    你可以这样称呼它:

    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;
    
      except
        on e: Exception do
        begin
          MadExcept.HandleException();
    
          raise EOleSysError.Create('InitializeObject Failed',
            ErrorNumberToHResult(1 + CODE_BASE), 1);
        end;
    
    try
      raise exception.create('test');
    except
      //eat exception
    end;
    
    类似的东西应该有一个{$DEFINE}来启用这些日志功能,启用/禁用诊断日志


    查看质量中心的58409报告

    这是关于FPU掩码和Dll的

    简而言之:

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

    例如,如果您有一个应用程序_A(由其他人编码),它加载Dll_A(也由其他人编码)和Dll_B(由您编码),并且您的Dll更改了FPU掩码,则此更改也对应用程序_A和Dll_A有效

    让我们举个例子: 您已经安装了WinZIP、SubVersion等,在windows文件资源管理器(鼠标右键单击弹出菜单)中注册了其他功能,现在您可以从application.exe内部调用TOpenDialog,那么这些附加功能可能会损害您的FPU设置

    希望这有帮助。 (附加提示:使用Sysinternal查看应用程序加载了哪些dll)

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

    大概是这样的:

    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;
    
      except
        on e: Exception do
        begin
          MadExcept.HandleException();
    
          raise EOleSysError.Create('InitializeObject Failed',
            ErrorNumberToHResult(1 + CODE_BASE), 1);
        end;
    
    try
      raise exception.create('test');
    except
      //eat exception
    end;
    
    如果应用程序挂起但未抛出和异常,则可以使用MadException实用程序madTraceProcess查看发生的情况。这将允许您为正在运行的应用程序生成调用堆栈。您的dll将不在主线程上,但您将能够看到您的调用堆栈。当挂起发生时,这是一个很好的方法来判断dll是否真的在做任何事情


    我有一个COM dll,它可以与不使用MadExcept的exe进行交互,这种方法对我来说非常有效。

    如果我正确地理解了这种情况,那么如果dll没有崩溃,并且被调用的第三方程序停止响应,您就没有什么可以做的了。崩溃在他们的代码中,但仅由DLL调用它触发。调试日志确实应该在他们的应用程序中完成。
    不过,您可以做的是使用参数和一些上下文信息记录DLL对此第三方程序的所有调用。

    然后看看坠机前的最后一条线索可能会给你一些信息…

    我不知道MADEEXPECT是如何工作的,但我经常使用jclDebug.pas+JclHookExcept.pas(来自绝地JCL库)。它创建了一个Windows API挂钩,因此它可以捕获所有(!)异常,即使您创建了如下内容:

    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;
    
      except
        on e: Exception do
        begin
          MadExcept.HandleException();
    
          raise EOleSysError.Create('InitializeObject Failed',
            ErrorNumberToHResult(1 + CODE_BASE), 1);
        end;
    
    try
      raise exception.create('test');
    except
      //eat exception
    end;
    
    通常你不会看到这个异常,因为它被“吃掉”。。。但有了钩子,你会得到所有的例外。例如:我有一次在Midas.dll中遇到了一个“灾难性的失败”,通过这个钩子,我在这个异常之前看到了dll中的一个“数据库连接丢失”错误,所以我知道发生了什么。(顺便说一句:JclHookExcept.pas=hook,jclDebug.pas=strack跟踪)

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

    一些演示代码:

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

    我非常同意。我以前多次到过这个地方,最快的解决方案总是创建一个新的可重复测试程序,并将其提供给具有完整源代码的供应商。如果可能的话,记录与API的所有交互(传递的参数和返回的参数)。供应商说Dave的DLL是错误的。供应商是应该制定测试程序的人,而不是Dave,因为供应商才是真正看到问题的人。如果不是一个测试程序,那么至少有一个步骤列表来说明问题。我认为供应商没有看到这一点。我以为是戴夫的顾客。无论如何,我同意vendo