|

- UID
- 11558
- 帖子
- 5
- 积分
- 86
- 威望
- 2 点
- A币
- 27 元
- 阅读权限
- 10
- 最后登录
- 2007-7-6
|
2#
发表于 2006-6-16 14:37
| 只看该作者
二 数据断点(Data Breakpoint)
软件调试过程中,有时会发现一些数据会莫名其妙的被修改掉(如一些数组的越界写导致覆盖了另外的变量),找出何处代码导致这块内存被更改是一件棘手的事情(如果没有调试器的帮助)。恰当运用数据断点可以快速帮你定位何时何处这个数据被修改。譬如下面一段程序: #include "stdafx.h"
#include
int main(int argc, char* argv[])
{
char szName1[10];
char szName2[4];
strcpy(szName1,"shenzhen");
printf("%s\n", szName1); //A
strcpy(szName2, "vckbase"); //B
printf("%s\n", szName1);
printf("%s\n", szName2);
return 0;
}
这段程序的输出是 szName1: shenzhen
szName1: ase
szName2: vckbase
szName1何时被修改呢?因为没有明显的修改szName1代码。我们可以首先在A行设置普通断点,F5运行程序,程序停在A行。然后我们再设置一个数据断点。如下图:
Figure 2 数据断点
F5继续运行,程序停在B行,说明B处代码修改了szName1。B处明明没有修改szName1呀?但调试器指明是这一行,一般不会错,所以还是静下心来看看程序,哦,你发现了:szName2只有4个字节,而strcpy了7个字节,所以覆写了szName1。
数据断点不只是对变量改变有效,还可以设置变量是否等于某个值。譬如,你可以将Figure 2中红圈处改为条件”szName2[0]==''''y''''“,那么当szName2第一个字符为y时断点就会启动。
可以看出,数据断点相对位置断点一个很大的区别是不用明确指明在哪一行代码设置断点。
三 其他
1 在call stack窗口中设置断点,选择某个函数,按F9设置一个断点。这样可以从深层次的函数调用中迅速返回到需要的函数。
2 Set Next StateMent命令(debug过程中,右键菜单中的命令)
此命令的作用是将程序的指令指针(EIP)指向不同的代码行。譬如,你正在调试上面那段代码,运行在A行,但你不愿意运行B行和C行代码,这时,你就可以在D行,右键,然后“Set Next StateMent”。调试器就不会执行B、C行。只要在同一函数内,此指令就可以随意跳前或跳后执行。灵活使用此功能可以大量节省调试时间。
3 watch窗口
watch窗口支持丰富的数据格式化功能。如输入0x65,u,则在右栏显示101。
实时显示windows API调用的错误:在左栏输入@err,hr。
在watch窗口中调用函数。提醒一下,调用完函数后马上在watch窗口中清除它,否则,单步调试时每一步调试器都会调用此函数。
4 messages断点不怎么实用。基本上可以用前面讲述的断点代替。
总结
调试最重要的还是你要思考,要猜测你的程序可能出错的地方,然后运用你的调试器来证实你的猜测。而熟练使用上面这些技巧无疑会加快这个过程。最后,大家如果有关于调试方面的问题,我乐意参与探讨。
#include"windows.h"
#define VK_x 0x58
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdshow)
{if(!CreateMutex(NULL,TRUE,"No Previous Instance!"))
{MessageBox(NULL,"创建Mutex失败","NoPrev",MB_OK|MB_SYSTEMMODAL);
return FALSE;}
if(GetLastError()==ERROR_ALREADY_EXISTS)
{
MessageBox(NULL,"已有NoPrev的一个实例在运行,当前实例被终止境","NoPrev",MB_OK|MB_SYSTEMMODAL);
return FALSE;}
if(!RegisterHotKey(NULL,0x0001,MOD_CONTROL|MOD_SHIFT,VK_x))
{
MessageBox(NULL,"注册热键ctrl+shift+x失败","Noprev",MB_OK|MB_SYSTEMMODAL);
return FALSE;}
MessageBox(NULL,"NoPrev已启动!\n\n按下热键ctrl+shift+x将终止NoPrev.","NoPrev",MB_OK|MB_SYSTEMMODAL);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{switch (msg.message)
{case WM_HOTKEY:
if (int(msg.wParam)==0x0001)
if(MessageBox(NULL,"终止NoPrev?","NoPrev",MB_OK|MB_SYSTEMMODAL)==IDYES)
return true;}}
return true;} |
|