我如何调试ActiveX控件(OCX),或使其记录错误?(How can I debug an ActiveX control (OCX), or make it log errors?)

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

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

每秒大约10次Borland应用程序获得一个新的位置,并找出哪些形式(及其ActiveX)需要知道更新的位置以便绘制它。 这已经很长时间了,但是我必须对ActiveX的新版本做一些改变。

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

现在,随着我所做的最近更改,我遇到了同样的问题,其中一个组件似乎出现了一个错误,而这个错误没有被显示出来,而是没有重新绘制自己,而且内存的使用也变得越来越高。 在某些PC上,似乎存在访问冲突 - 这是说错误发生在OCX中,但在我开发的个人电脑上,我无法以任何方式获得此访问冲突。

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

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

我非常确定组件内部发生了一些错误,而这些错误并未传递,所以我看不到它是什么。

那么有谁知道我可以如何调试? 我可以以某种方式使OCX日志发生任何错误,或使其显示错误,或者我能做什么?

任何帮助将非常感谢 - 一直试图追查3天的错误,但没有结果。

I'm currently working with a rather old Borland C++ application, which is using an ActiveX component to draw some graphics. In the application multiple windows with the ActiveX comp. can be open at any time - these can either show the same graphics (different zoom factor etc), or different graphics.

The application is for positioning, and the ActiveX is drawing and showing positions of different units.

Around 10 times a second the Borland application got a new position, and finds out which forms (and their ActiveX) needs to know about the updated position in order to draw it. This have been going well for a long time, but I have had to do quite some changes in the ActiveX for a new version of the product.

About a year ago I had to do some minor changes in the component aswell, and I found that the application could end in a state, causing an "index out of bounds" error in the component. The result of this was not an error getting shown or the program terminating, but instead the application started to use a huge amount of memory - and kept going up very fast. At some point it stopped and the component that had the error simply stopped showing anything (stopped drawing itself).

Now with the recent changes I have made, I have the same problem where one of the components seems to get an error, which is not getting shown, and instead it is not redrawing itself, and the memory use is going sky-high. On some PC's it seems that an Access Violation is thrown - which is saying that the error happened in the OCX, but on the PC I develop on, I cant get this Access Violation in any way.

Also I cannot track down exactly when the error happens - ie what is causing the error. I can run the same setup 10 times in a row for 15 minutes, sometimes it happens that the memory use go up and a component bug, other times nothing happens and it runs as it should for the whole duration.

As it is an OCX, it is registered using regsvr32, and is therefore code-wise not part of the main application. Therefore I can not use breakpoints and debug it that way.

I am pretty sure that some error is happening inside the component, which is not passed on, so I cannot see what it is.

So do anyone know how I can debug this? Can I somehow make the OCX log any errors that happens, or make it show the error, or what can I do?

Any help would be much appreciated - been trying to track down the error for 3 days now with no result what so ever.

最满意答案

基本上你在问如何调试一个DLL。 OCX只是一个加载到进程中的DLL文件。 这是一个比较宽泛的话题,但我会尽量给出一个简短的开始:

在Windows编程中,DLL / EXE / OCX文件通常被称为“模块”。 他们基本上都是一样的东西。 为了清楚起见,我会在这里称它们为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甚至为像ntdll.dll这样的Windows DLL提供PDB文件。 必须根据需要下载它们。 Visual Studio可以通过转至Tools -> Options -> Debugging -> Symbols自动执行此Tools -> Options -> Debugging -> Symbols并且应该有一个选项可以使用Microsoft Symbol Server自动提取缺失的符号文件。

小例子让你朝正确的方向发展:

假设您编写了一个名为myctl.ocx的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). ...

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

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

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

Essentially you are asking how to debug a DLL. An OCX is just a DLL file that's loaded into a process. This is a somewhat broad topic, but I'll try to give a brief start:

DLL / EXE / OCX files are usually called "modules" in the context of Windows programming. They are all basically the same thing. I will call them DLLs here though just for the sake of clarity.

Debuggers (Visual Studio and Borland are both debuggers as well as IDEs) "attach" like a parasite to processes, allowing you to do things like set breakpoints, read process memory, see stack trace, etc. They can see / manipulate all the memory & resources for that process including all DLLs.

DLLs do not contain much information to help debuggers, even in a debug build. They basically just contain binary machine code and if you step into a DLL call with the debugger, you'll only be able to see the assembly code -- not the original source code. Functions are just addresses in memory, local variables are not even visible; you only get some pointers into stack memory.

PDB files ("program database") contain all the additional information and metadata for the debugger to do things like mapping addresses in memory to lines of source code, local variables, datatypes, function signatures, etc. This information is called "debugging symbols" or just "symbols". When Visual Studio builds a DLL, it outputs a corresponding PDB file. It's this PDB file that enables all the magic of stepping through your source code in the debugger, viewing local variables, viewing datatypes properly in the watch window.

When Visual Studio's debugger is attached to a process and sees a DLL being loaded, it searches for its corresponding PDB file. It looks for this in a number of places - the simplest of which is in the same folder as the DLL. So if you loaded C:\something\myctl.ocx, it will look for C:\something\myctl.pdb. If it can find it, it will use it and you can debug the DLL with rich debugger support. If it can't find it, you will be where you are now - where DLL calls are a black box you cannot see into.

Microsoft even provides PDB files for Windows DLLs like ntdll.dll. They must be downloaded as needed. Visual Studio can do this automatically by going to Tools -> Options -> Debugging -> Symbols and there should be an option to use Microsoft Symbol Servers to automatically fetch missing symbol files.

Small example to put you in the right direction:

Let's say you wrote an OCX called myctl.ocx that crashes when it's added to a Wordpad document. The way to debug this is to attach the debugger to wordpad.exe. In Visual Studio that's Debug -> Attach to Process I believe. When it's attached, you can even see in the output window:

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

You can see how Visual Studio loads the PDB files (symbol files) that provide a bit of extra information for these. When you load myctl.ocx, you will see that line as well. If myctl.pdb is accessible, it will load that as well.

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

With this, you can debug anything in myctl.ocx with source code and everything. When Wordpad crashes inside of myctl.ocx, it should show you the source code and everything, again assuming it's in an accessible location.

更多推荐