2009-06-25 103 views
4

我寫了一個德爾福DLL通過COM與第三方程序進行通信。一些用戶報告說第三方程序偶爾崩潰。其他人以相同的方式使用軟件從未遇到過崩潰。發生這種崩潰時,第三方程序似乎只是在我的DLL應用程序中變得不可用。德爾福應用程序通訊偶爾會導致崩潰 - 供應商導致我的德爾福應用

供應商發誓,雖然他們沒有看到源代碼,也不知道DLL是如何導致崩潰的,但它是Delphi DLL編碼的問題,但他們知道這是「某種東西」。

除了我相信第三方程序不應該因我的DLL中的一些微小問題而崩潰的事實,讓我們假設我的DLL中有某些東西需要修復。

如何確定我的應用程序如何導致此問題?有沒有人有通過COM與這種超敏感程序進行通信的經驗?是否有一些常見的事情可能會導致第三方程序崩潰?

回答

4
  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}啓用這些日誌記錄功能,以啓用/禁用診斷日誌記錄。

This could also be useful.

2

如果他們的程序在使用他們發佈的界面時崩潰,我很確定它有什麼問題。證明這是另一回事。

你可以用一個小的Delphi應用程序可靠地重現問題,你可以給供應商?看到可重現的失敗可能有助於說服他們需要修復。至少,它可以幫助確定他們認爲自己在做什麼「錯誤」,並告訴你如何做到「正確」。

您也可以嘗試使用C#甚至VBScript來複制失敗。

+0

我非常同意。我以前曾經在這個地方工作過很多次,最快的解決方案一直是創建一個新的可重複測試程序,並將其提供給供應商提供完整的源代碼。如果可能,記錄與API的所有交互(正在傳遞哪些參數以及返回的內容)。 – skamradt 2009-06-25 16:16:41

+4

供應商說Dave的DLL是錯誤的。供應商是誰應該制定測試計劃,而不是戴夫,因爲供應商是真正看到問題的人。如果不是測試程序,那麼至少要列出一系列步驟來證明問題。 – 2009-06-25 17:39:25

+1

我不認爲供應商看到這個。我認爲這是戴夫的顧客。無論如何,我同意供應商應該加強工作,至少幫助解決問題。不幸的是,他們似乎並不急切,所以落到戴夫身上可以幫助他們說服他們存在問題,或者找到解決辦法。誰知道,重複這個問題,他可能會發現他畢竟犯了一個錯誤。底線;戴夫讓他的顧客擔心。 – 2009-06-25 19:14:48

4

看質量爲中心報告58409.

這是關於FPU面具和DLL的。

解釋它在短:

的FPU面膜determ的浮點異常是如何處理的設置。如果你有例如載入Dll_A(也由其他編碼)和Dll_B(由你編碼)的Applicaion_A(由其他編碼),並且你的Dll改變了FPU掩碼,那麼這個改變對於Application_A是有效的和Dll_A。

讓我們來舉個例子吧: 你已經安裝了例如WinZIP,SubVersion等在windows文件資源管理器中註冊附加功能(右鍵單擊彈出菜單),現在你可以從application.exe中調用TOpenDialog,那麼這些附加功能可能會危及您的FPU設置。

希望這會有所幫助。 (附加提示:以Sysinternal來查看你的應用加載了哪些dll)

3

你有沒有考慮過使用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交互,這種方法對我來說效果很好。

2

如果我正確理解了這種情況,不幸的是,如果你的DLL沒有崩潰,並且被叫第三方程序停止響應,那麼你可以做的事情不多。崩潰是在他們的代碼中,但只是由您的DLL調用它引發的。調試日誌應該真的在他們的應用程序中完成。
你可以做的是通過參數和一些上下文信息記錄你的DLL對第三方程序的所有調用。
然後看最後一絲之前崩潰可能給你一些信息...

2

我不知道該怎麼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也有一個「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);