如何调试ActiveX控件(OCX)或使其记录错误?

Kni*_*ard 5 c++ debugging error-handling mfc activex

我目前正在使用一个相当古老的Borland C++应用程序,它使用ActiveX组件绘制一些图形.在应用程序中使用ActiveX comp的多个窗口.可以随时打开 - 这些可以显示相同的图形(不同的缩放系数等),也可以显示不同的图形.

该应用程序用于定位,ActiveX正在绘制并显示不同单元的位置.

每秒大约10次Borland应用程序获得一个新位置,并找出哪些形式(及其ActiveX)需要知道更新的位置以便绘制它.这已经进行了很长时间,但我不得不在ActiveX中为新版本的产品做一些更改.

大约一年前,我不得不对组件进行一些小的更改,并且我发现应用程序可能以某种状态结束,导致组件中出现"索引越界"错误.结果不是显示错误或程序终止,而是应用程序开始使用大量内存 - 并且继续快速上升.在某些时候它停止了,有错误的组件只是停止显示任何东西(停止绘制自己).

现在我已经做了最近的改变,我遇到了同样的问题,其中一个组件似乎得到一个错误,没有得到显示,而是它没有重绘自己,并且内存使用是天高的.在一些PC上,似乎抛出了访问冲突 - 这就是说错误发生在OCX中,但是在我开发的PC上,我无法以任何方式获得此访问冲突.

此外,我无法准确追踪错误发生的时间 - 即导致错误的原因.我可以连续10次运行相同的设置15分钟,有时会发生内存使用上升和组件错误,有时没有任何反应,它会在整个持续时间内运行.

由于它是OCX,因此使用regsvr32进行注册,因此代码不是主应用程序的一部分.因此我不能使用断点并以这种方式调试它.

我很确定组件内部发生了一些错误,但是没有传递,所以我看不出它是什么.

那么有谁知道如何调试这个?我可以以某种方式使OCX记录发生的任何错误,或使其显示错误,或者我该怎么办?

任何帮助将不胜感激 - 一直试图追踪错误3天,没有任何结果.

ten*_*our 10

基本上你问的是如何调试DLL.OCX只是一个加载到进程中的DLL文件.这是一个有点宽泛的话题,但我会尝试简单介绍一下:

DLL/EXE/OCX文件通常在Windows编程环境中称为"模块".它们基本上都是一样的.我会在这里称它们为DLL,但为了清楚起见.

调试器(Visual Studio和Borland都是调试器和IDE)将"寄生"作为进程的"寄存器",允许您执行诸如设置断点,读取进程内存,查看堆栈跟踪等操作.它们可以查看/操作所有内存和该进程的资源,包括所有DLL.

即使在调试版本中,DLL也不包含太多信息来帮助调试器.它们基本上只包含二进制机器代码,如果您使用调试器进入DLL调用,您将只能看到汇编代码 - 而不是原始源代码.函数只是内存中的地址,局部变量甚至不可见; 你只能得到一些指向堆栈内存的指针.

PDB文件("程序数据库")包含调试器的所有附加信息和元数据,用于将内存中的地址映射到源代码行,局部变量,数据类型,函数签名等.此信息称为"调试符号"或者只是"符号".当Visual Studio构建DLL时,它会输出相应的PDB文件.正是这个PDB文件实现了在调试器中逐步执行源代码,查看局部变量,在监视窗口中正确查看数据类型的所有魔力.

当Visual Studio的调试器附加到进程并看到正在加载的DLL时,它会搜索其对应的PDB文件.它在许多地方寻找它 - 最简单的地方与DLL在同一个文件夹中.因此,如果您加载C:\something\myctl.ocx,它将寻找C:\something\myctl.pdb.如果它可以找到它,它将使用它,你可以调试DLL具有丰富的调试器支持.如果它找不到它,你将成为现在的位置 - DLL调用是一个你无法看到的黑盒子.

Microsoft甚至为Windows DLL提供了PDB文件ntdll.dll.必须根据需要下载它们.Visual Studio可以自动执行此操作,Tools -> Options -> Debugging -> Symbols并且应该有一个选项可以使用Microsoft Symbol Servers自动获取丢失的符号文件.

一个小例子,让你朝着正确的方向:

假设你写了一个名为OCX的OCX myctl.ocx,当它被添加到一个Wordpad文档时会崩溃.调试方法是将调试器附加到wordpad.exe.在Visual Studio中,Debug -> Attach to Process我相信.连接后,您甚至可以在输出窗口中看到:

'wordpad.exe': Loaded 'C:\Program Files\Windows NT\Accessories\wordpad.exe', Symbols loaded (source information stripped).
'wordpad.exe': Loaded 'C:\Windows\System32\ntdll.dll', Symbols loaded (source information stripped).
'wordpad.exe': Loaded 'C:\Windows\System32\kernel32.dll', Symbols loaded (source information stripped).
'wordpad.exe': Loaded 'C:\Windows\System32\KernelBase.dll', Symbols loaded (source information stripped).
...
Run Code Online (Sandbox Code Playgroud)

您可以看到Visual Studio如何加载PDB文件(符号文件),这些文件为这些文件提供了一些额外的信息.加载时myctl.ocx,您也会看到该行.如果myctl.pdb可以访问,它也会加载它.

'wordpad.exe': Loaded 'C:\something\myctl.ocx', Symbols loaded.
Run Code Online (Sandbox Code Playgroud)

有了这个,您可以myctl.ocx使用源代码和所有内容调试任何内容.当Wordpad崩溃时myctl.ocx,它应该显示源代码和所有内容,再次假设它位于可访问的位置.