5

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

该应用程序用于定位,ActiveX 用于绘制和显示不同单元的位置。

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

大约一年前,我还不得不对组件进行一些小改动,我发现应用程序可能会以某种状态结束,从而导致组件中出现“索引越界”错误。这样做的结果不是显示错误或程序终止,而是应用程序开始使用大量内存 - 并且一直在快速增长。在某些时候它停止了,并且出现错误的组件只是停止显示任何东西(停止绘图本身)。

现在,随着我最近所做的更改,我遇到了同样的问题,其中一个组件似乎出现了错误,没有显示出来,而是没有重新绘制本身,并且内存使用量正在飙升。在某些 PC 上,似乎引发了访问冲突 - 这表示错误发生在 OCX 中,但在我开发的 PC 上,我无法以任何方式获得此访问冲突。

此外,我无法准确追踪错误发生的时间 - 即导致错误的原因。我可以在 15 分钟内连续运行 10 次相同的设置,有时会发生内存使用增加和组件错误,其他时候什么也没有发生,并且它在整个持续时间内都正常运行。

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

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

那么有人知道我该如何调试吗?我可以以某种方式让 OCX 记录发生的任何错误,或者让它显示错误,或者我能做什么?

任何帮助将不胜感激 - 现在已经尝试追踪错误 3 天,但没有任何结果。

4

3 回答 3

11

本质上,您是在问如何调试 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 调用是一个您无法看到的黑盒子。

微软甚至为 Windows DLL 提供 PDB 文件,例如ntdll.dll. 必须根据需要下载它们。Visual Studio 可以通过转到自动执行此操作,Tools -> Options -> Debugging -> Symbols并且应该有一个选项来使用 Microsoft 符号服务器自动获取丢失的符号文件。

让您朝着正确方向前进的小例子:

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

'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).
...

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

'wordpad.exe': Loaded 'C:\something\myctl.ocx', Symbols loaded.

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

于 2012-09-06T10:53:15.820 回答
1

如何在IE.10 + WIN8 64bit + VS2008下调试OCX/C++

  • 在 vs2008 中构建您的 ocx,将 ocx CSID 标签添加到您的 html 中。
  • 保持 TabProcGrowth 为中等(不改变!!)
  • 使用命令设置VS2008 OCX项目调试C:\Program Files (x86)\Internet Explorer\iexplore.exe,Attach = Yes,Debugger Type=Native Only
  • 打开 Internet Explorer 10 窗体 WIN8 任务栏。
  • 在 Internet Explorer 10 的 url 中键入目标 ocx htm 文件路径。然后按 enter 键加载 htm。
  • 加载了 ocx,您需要启用 IE.10 ActiveX 模式。
  • 当 IE10 准备好 ActiveX 模式时,运行您的 VS2008 OCX 项目,该项目会将 IE10 与您的断点连接起来。
  • 再次刷新 IE.10 html 以重新加载 ocx 并开始调试您的 ocx 源代码。
于 2014-04-26T23:04:11.140 回答
1

将代码添加到 OCX,它会打开一个文件并打印正在发生的事情,可能带有时间戳。日志内容可能包括执行流程、输入值、关键变量值、重要的内部状态。

至少我会这样处理它。

于 2012-09-06T10:08:49.407 回答