Google
 

VC调试:两个有个性的bug

昨天在用VC调试cnbook时碰到两个有个性的bug:

1 bug1和Release版本调试

这个bug不能用调试器。我用加打印的方式调试。 对于GUI程序,将打印输出送到另一个窗口就可以了。附录1介绍了我常用的GUI程序打印方法。

通过一步步增加打印,我发现问题是一个零结尾的字符串参数引起的。 如果结尾零后面是非零值就不会错。 如果结尾零后面还是零就会出错,这也就是直接运行Release版本时发生的情况。

发现问题原因后,我就可以用调试器了。 调试Debug版本,在输入参数前断下来,将结尾零后面的数据改成0。 然后就可以在调试器中跟踪运行。最后发现有一个函数没有判断字符串已经结束了,加个判断就好了。

2 bug2

bug2在调试中能出现就很容易调了。bug很简单:我有一个函数期待零结尾的C字符串。 但我在一些调用的地方,传入字符串没有以零结尾,导致读数据越界。 在Release版本,可能字符串后面有零字符,没有出现问题。 在Debug版本,字符串后面很长一段都没有零字符,所以出现问题。

3 结束语

在VC调试中还有一个比较神奇的bug就是在调试状态弹出User breakpoint 的提示,我也碰到过几次。 这是写越界,破坏堆数据引起的。解决方法可以见 “除虫记之十二:费解的NTDLL断点”

其实不管有没有暴露出来,bug总是存在的,就像不管晴天雨天,太阳总是存在的。 解决所有bug的最好方法还是在开发时再细心一些,不要让它们出现。

附录1 GUI程序的打印调试

我写过一个叫作MsgWin的小程序,它可以将WM_COPYDATA消息中的打印文本显示出来。 在MsgWin中选择“工具”->“窗口名称”->“打印窗口”,将MsgWin的窗口名称设为“打印窗口”。 然后在调试的程序中用FindWindow查找名称为“打印窗口”的窗口,将打印输出通过WM_COPYDATA消息发给它就可以了。

WM_COPYDATA消息的LPARAM参数的数据结构COPYDATASTRUCT定义如下:

typedef struct tagCOPYDATASTRUCT {
    DWORD dwData;
    DWORD cbData;
    PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

cbData是数据长度,单位是字节。lpData是数据指针。 WM_COPYDATA消息必须用SendMessage同步发送,所以指针指向的数据只要在调用SendMessage时有效就可以了。 MsgWin支持消息级别,也支持ANSI编码或Unicode编码的文本。这些信息都通过dwData传递:

我整理了一个压缩包,包括MsgWin、MsgWin源程序和放在调试对象中的打印代码。打印代码有ANSI和UNICODE两个版本。

 

Google
 

个人主页留言本我的空间我的程序 fmdd@263.net