供应商声称这是Delphi DLL编码方式的问题,尽管他们没有看到源代码,无法确定DLL导致崩溃的具体原因,但他们知道这是“某个问题”。
除了我认为第三方程序不应因我的DLL中的微小问题而崩溃之外,让我们假设我的DLL确实需要修复一些东西。
如何确定我的应用程序可能会引起这种情况?有没有人有使用COM与这样超敏感程序通信的经验?有没有一些常见的事情需要查找,可能会导致第三方程序崩溃?
以下是示例:
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的Quality Central。
它涉及FPU掩码和Dll。
简单来说,FPU掩码的设置决定了如何处理浮点异常。
例如,如果您有一个由其他人编写的Application_A,它加载了Dll_A(也由其他人编写)和您编写的Dll_B,并且您的Dll更改了FPU掩码,则此更改对Application_A和Dll_A同样有效。
让我们举个例子: 您已安装WinZIP、SubVersion等,这些软件在Windows文件资源管理器中注册了附加功能(右键单击弹出菜单),然后您从应用程序.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等工具是如何工作的,但我经常使用jclDebug.pas + JclHookExcept.pas(来自JEDI JCL库)。它会创建一个Windows API钩子,因此可以捕获所有(!)异常,即使您像这样做:
try
raise exception.create('test');
except
//eat exception
end;
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);
如果我正确理解了情况,不幸的是,如果您的DLL没有崩溃而被调用的第三方程序停止响应,那么您在您这一侧无法做太多事情。 崩溃是发生在他们的代码中,但只有通过您的DLL调用才会触发。 调试日志应该真正在他们的应用程序中完成。
不过,您可以记录您的DLL对这个第三方程序的所有调用,包括参数和一些上下文信息。
然后,在崩溃之前查看最后一条跟踪可能会给您一些信息...