下面有从浅入深的6个问题,您可以尝试回答一下

  1. 一个如下的语句for (int i = 0; i < 10; i++){if (i == 5)j = 5;},什么都写在一行,你怎么在j=5前面插入断点
  2. 在一个1000次的循环体内部设置断点,你希望当循环进行到900次后中断,怎么才能做到呢?
  3. 你有一个表达式在上面循环的某一次发生了变化,你想知道是哪一次,在哪个地方,怎么才能做到?
  4. 你希望你的断点在被命中100次后,每命中三次中断一次,比如第103,第106,第109怎样做?
  5. 你有在调试一个服务程序,希望在其内部打上了断点,可是,由于这是一个公用的服务你不希望其他访问这个服务的程序被你的调试所干扰,你想怎么办?
  6. 怎样知道2个断点中断的时间间隔

问题1,2

这两个问题最简单,我在一个例子里说明

例如如下循环

for(int i=0;i<1000;i++){doSomeThing......}

在循环的大括号上单击右键,插入断点,用这个方法,可以对付那些喜欢把语句写在一行上的家伙,其实,随着.Net3.5中Linq的出现,我们肯定也会经常在在一行上写复杂的表达式,这个时候用这种插入方法会比较管用

ok,现在我们来编辑这个断点的条件,在断点上右键单击,选择如图菜单项

在弹出的窗口中可以设置断点命中的条件i==900

注意我是在调试C#代码,默认的条件语句语法是C#,如果你想切换,那就需要用Ctrl-B,来插入断点,并在弹出窗口中选择语言

通过这样设置条件断点,我们就可以解决我们的问题1,2了

问题3

同样通过设置条件断点我们还可以解决我们的问题3,对表达式变化的跟踪

string user="yizhu2000"

for(int i=0;i<10000;i++){

DoSomething1()

.......

DoSomethingN()

}

当循环执行完毕时我们发现user变成了"smart_boy",你不知道这个值是在第几次循环的时候变化的,那么你是不是会选择打上断点,一次一次中断,来查看呢?当然不用

在循环体结束的位置我们设置一个断点,打开条件编辑窗口(打开方法同上),设置表达式为user,勾选下面的HasChanged,也就是说,你告诉断点,当user的值发生变化时才触发

(注意:第一次执行到断点的时候,程序一定会中断,并计算这时表达式的值,所以,所谓发生变化,指的是以后执行到断点是表达式的值和第一次执行到断点时表达式的值的比较)

问题4

如何让断点在指定的命中次数或者大于某个次数时触发呢?方法是设定几个断点的HitCount,右键单击断点,在弹出菜单中选择Hit Count,会弹出如下窗口

在"when the break point is hit"下拉列表里,我们可以看到四个选项

break always:总是中断

break when the hit count is equal to:等于某次数时中断

beak when the hit count is a multpile of:当次数是某数的倍数时中断

break when the hit count is greater than or equal to:当大于等于某数时中断

问题5

前面4个问题都已经解决了,第5个问题的解决方法是利用断点的Filter功能,比如我希望断点只有被机器名为yizhu的机器访问才能触发,我可以这样设置

当其他机器访问程序的时候,断点将不会触发,这样做的优点是通过设置机器名,我们可以让其他机器访问的时候感觉不到断点的存在,除此之外我们可以设 置机器名,进程号,进程名,线程号,线程名作为filter,而且还可以把他们组合起来,比如我希望通过当机器yizhu的dllhost进程调用时才触 发,那么问题就可以设置为MachineName="yizhu"&ProcessName="dllhost"

问题6

现在我们来解决第6个问题:

在程序性能调试的时候,我们经常需要知道某段代码的执行效率,一般来说,我们可以在程序中加入时间点,通过时间点相减来取得时间间隔,这种方法有个 显而易见的缺点就是需要修改程序,想要不修改程序,就需要借助一些工具,那么有没有什么方法可以声明式的插入时间点,并计算值呢?其实断点完全可以做到

在给出方法前,我们来看看断点的另外一个设置项,When Hit,这个选项可以让我们在命中断点后做一些事情,包括输出一些内容,或者调用宏,比如输出一个程序中变量的值

我们输出了变量user的值,下面Continue Execution表示程序不会中断,输出后继续执行,注意表达式需要用{}括起来,,其他的部分会被作为字符串输出。设定WhenHit后断点变成了方形(看厌了圆断点,我还挺喜欢这个方家伙的)

在output中查看输出结果,如下:

既然可以计算表达式,我们的第一个最简方案就出来了,也就是在程序执行到断点的时候,输出DateTime.Now,这样当然是可行的,但是我们需 要的是时间间隔,所以我们还需要自己来算个减法,还是挺麻烦的,怎么样才能让程序自己输出时间间隔呢?有一个想法是这样的,我们在上一个断点声明一个时间 变量,然后在下面的断点里用DataTime.Now减去这个变量,即

断点一的条件:{DateTime _t=DateTime.Now;}

断点二的条件:{DateTime.Now-t;}

看起来不错,但是实际运行时就有问题了,让我们看看输出吧

上面高亮的部分说,变量申明只能在immediate window中进行,所以断点一的变量没有申明成功,关于immediatewindow,我们以后会涉猎到,反正就是说想在表达式里申明变量,没门,死路一条.那么我们怎么才能不申明变量又时间点呢?

这时我想起了Thread.SetData 方法,这个方法可以往当前线程专门提供的空间中插入一些数据,并且可以通过GetData得到数据,具体细节参考

http://msdn2.microsoft.com/zh-cn/library/system.threading.thread.setdata(VS.80).aspx

于是方案就有了,在第一个断点处把时间放入Thread的DataSlot,然后第二个断点取出来相减

断点一的条件:{Thread.SetData(Thread.GetNamedDataSlot("ExecutionTime"),DateTime.Now);}

断点二的条件:{DateTime.Now-(DateTime)System.Threading.Thread.GetData(System.Threading.Thread.GetNamedDataSlot("ExecutionTime"));}

看看输出效果

我们的目的已经达到了,output中成功的输出了时间间隔,当然,还不是很完善,首先,这个方法限于两个断点,你想多打几个断点,测试两两间的间隔还是比较麻烦.测量精度也可以提高,大家有兴趣可以自己研究这个方法的扩展

《高效编程十八式》(11/13)调试

http://blog.sina.com.cn/s/blog_4ed027020100hgr6.html

调试

王伟冰

调试可以深入程序内部,观察运行时各个变量的值。但是,并不是一出现bug就要调试。调试最适合用来探究一些自己不太熟悉的语言特性或者是技术。比如你对C某些语句的作用不太熟悉,对某个库函数的作用不太熟悉,调试一下,就可以看得清清楚楚了。如果程序只是逻辑出错误,最好的方法是测试,通过逐个单元的测试,找出问题的所在。为什么测试的效率更高?因为测试可以是自动化的,你可以编写测试代码,一次性地完成很多测试,但调试只能一步一步地来。调试的好处是可以直接看变量的值,而测试的话,必须写额外的代码把变量的值输出到控制台或者日志文件里。下面说一些调试的技巧。

   断点

最简单的一种,设置一个断点,程序执行到那一句就自动中断进入调试状态。

   单步执行

有三种,一种是每次执行一行;一种是每次执行一行,但遇到函数调用就会跳到被调用的函数里;一种是直接执行当前函数里剩下的指令,返回上一级函数。在Visual Studio中,上面三种方法对应的快捷键分别为F10、F11、Shift F11。

   监视

调试器可能会自动列出一些相关变量的值,但是你可能还关心其它变量的值,可以添加对这些变量的监视。还可以监视一个表达式的值,比如ab。但是,这个表达式最好不要修改变量的值,比如监视a 都会导致监视时修改了a的值,影响了程序的运行结果。

   条件中断

假如你有这样的循环:

for(int i=0;i<100;i ){

for(int j=0;j<100;j ){

……

}

}

你怀疑当i=10且j=10的时候执行有问题,那如何调试?用断点的话,从i=0的初始状态,需要中断10次才能到i=10,然后从j=0也需要再中断10次,才能到j=10的状态。所以想进入i=10且j=10的状态,需要中断20次,这太麻烦了。可以使用条件中断:

for(int i=0;i<100;i ){

for(int j=0;j<100;j ){

if(i==10 && j==10){

; //空语句

}

……

}

}

在空语句的那一行设置断点就可以了。

上面的if结构太占地方,还可以用assert:

assert(i!=10 || j!=10);

断言i不为10或j不为10,那么当i=10且j=10的时候,断言就不成立,程序就会中断,进入调试状态。

有时候用throw也可以中断:

if(i==10 && j==10)throw;

但是最好不要这样做,调试器不一定会在throw的地方中断。

   控制变量法

其实这已经不算是调试的内容了,但是也是一种找出bug原因的手段,所以还是在这里说。

控制变量法常用于科学研究中,比如说,研究牛顿第二定律a=F/m,a与F和m都有关,那么可以先固定m,研究a与F的关系;然后固定F,研究m与a的关系。

对于一个程序来说,一个bug可能跟多处代码有关。假如你怀疑这个bug与某些语句有关,可以把这些语句注释掉,或者是改一改,看看bug是否还存在,如果不存在,说明确实跟这些语句有关。(当然,要保证程序少了这些语句之后还可以顺利运行。)如果bug还存在,就说明它跟这些语句无关。

有些时候我们缺乏调试工具,比如在网页上运行的程序,在特殊设备上运行的程序,那么控制变量法是一种很有用的代替手段。

   二分法

二分法是控制变量法的进一步扩展。

在数学上,二分法用于求一个连续函数的根。比如一个函数f(x),如果f(x1)>0且f(x2)<0,那么在区间x1和x2之间,必定存在一个x,使f(x)=0。然后我们再考察区间的中点x3=(x1x2)/2,如果f(x3)>0,则函数的根就在区间x3和x2之间,如果f(x3)<0,那么函数的根就在区间x1和x3之间。如此不断地把区间一分为二,最后锁定函数的根。

对于一个程序来说,如果当前情况是有bug的,那就好比是f(x1)>0;如果你把main函数里所有的操作都注释掉,那么程序什么都不做,就不可能有bug,那就好比是f(x2)<0;于是在这两种状态之中,肯定存在一些临界的语句,当这些语句改动的时候,就会使程序在有bug和无bug状态间切换,这些语句就是bug的原因所在。运用二分法的思想可以锁定这些临界语句。一开始先对程序做一些大刀阔斧的改动,比如说,程序的主循环会循环10次,就改成1次;程序有10个功能,就关掉5个功能。看看哪些改动,可以让程序由有bug状态切换到无bug状态。找到这样改动后,就把这个改动再细分成几个小改动,比如关掉5个功能,就细分为关掉一两个功能,再看看哪些小改动可以让程序由有bug状态切换到无bug状态。如此一步一步缩小包围圈,就后锁定一个无法再分的小改动,这个改动就是bug的原因所在。

   同步法

有些bug是由于多线程而产生的。因为在不同线程里的操作我们无法预测其发生的顺序,可能当它们按某种次序进行时,bug不会出现,当它们按另一种次序进行时,bug就出现了。比如多线程那一节说到的那个银行帐户,如果没有加同步锁,就会出现这种bug。对这种bug的调试是很困难的,有时你运行程序发现了bug,而在进行调试的时候,由于执行顺序不同了,bug又不出现了。

为了解决这个问题,我想了一个办法,就是利用同步事件,强行把多线程的程序按照预定好的顺序去执行。比如说有两个线程,一开始就让线程1运行,线程2睡觉,线程1运行到某个特定的点后,就换线程2运行,线程1睡觉。任何时候,都只有一个线程可以运行。我们可以在多次运行的过程中使用不同的执行顺序,如果按某种执行顺序运行之后bug浮现了,那么就把这种顺序记录下来。然后按照这种顺序进入调试,找出bug。

用这种方法一定要谨慎,如果你的程序里本来就有线程同步的代码,再加上这些强制的同步,可以会导致死锁。

=============================================

Visual Studio调试(Debug)小技巧

http://hi.baidu.com/liudong/blog/item/d0434c08c6d315970b7b827e.html

在Visual Studio 运行调试过程中,有两个非常有用的小工具:
1,Command Window。
2,Immediate Window。

Command Window用于执行一些有用的命令。例如创建一个新文件可以使用命令:
        File.NewFile "abc.cpp"
有趣的是提供一个和Dos中cls类似命令。

ImmediateWindow提供在调试过程中运行一些有用的表达式,或者查看程序中的变量的值。例如程序中有两个变量a和b,现在要测试ab的值,可以使用下面的命令 (注意前面的>不可省略):
        >Debug.Print a b

MSDN参考:
ms-help://MS.MSDNQTR.v90.en/dv_vscmds/html/48711628-1909-4713-a73e-d7b714c77f8a.htm
ms-help://MS.MSDNQTR.v90.en/dv_vscmds/html/d33e7937-73f3-4c69-9df0-777a8713c6f2.htm

====================================

在vs2008 C 下调试控制台程序的心得及技巧

http://blog.sina.com.cn/s/blog_62466e480100f8cw.html

Visual Studio2008环境与VC6.0的环境存在着比较大的区别,下面就一些小小的区别在这里做一些探讨,欢迎指教!

1、如果是调试控制台程序,很多时候点击“启动调试”后是一闪而过,此时可有两种方法让cmd下dos调试屏幕暂停:

A:不要直接点击vs2008的“启动调试”按钮,而是按Control F5组合键。

B:在主函数main()里“return 0;”前加上两句:cin.get();样式如下

eg: int main()
         {
             cout<<"这是一个调试屏幕暂停的例子!"<<endl;
             cin.get();
             cin.get();
             return 0;
        }

2、类、函数和变量是C 编译器的标准组件,它们都放置在名称空间std中(此时头文件没有后缀名h)。在vs2008 C下,如果不包含using namespace std;指令,那么必须使用std::前缀,如

#include "stdafx.h"
#include<iostream>  //头文件没有h后缀名

void simon(int); //函数原型

//using namespacestd;    没有使用std名称空间

int _tmain(int argc, _TCHAR* argv[])
{
simon(3);
std::cout<<"请输入一个整数: ";//必须使用std::前缀,以下都是
int count;
std::cin>>count;
simon(count);
std::cout<<"完成!"<<std::endl;

std::cin.get();//这两行是使调试屏幕暂停,不会一闪而过
std::cin.get();//让程序等待键击
return 0;//退出主函数
}

void simon(int n) //自定义函数
{
std::cout<<"现在整数是"<<n<<"测试!"<<std::endl;
}

下面是一个使用using namespace std;名称空间的对比:

#include "stdafx.h"
#include<iostream>

void simon(int);

using namespace std; //这是一个使用std;名称空间的例子

int _tmain(int argc, _TCHAR* argv[])
{
simon(3);
cout<<"请输入一个整数: ";
int count;
cin>>count;
simon(count);
cout<<"完成!"<<endl;

cin.get();
cin.get();
return 0;
}

void simon(int n)
{
cout<<"现在整数是:"<<n<<"测试!"<<endl;
}

还有一种方法,就是既不使用std;名称空间,也不使用std::前缀,而是使用using编译指令。如:

#include "stdafx.h"
#include<iostream>

using std::cout; //直接使用using指令
using std::cin;
using std::endl;

void simon(int);

//using namespace std; //这是一个既没有使用std;名称空间也没有使用std::前缀的例子

int _tmain(int argc, _TCHAR* argv[])
{
simon(3);
cout<<"请输入一个整数: ";
int count;
cin>>count;
simon(count);
cout<<"完成!"<<endl;

cin.get();
cin.get();
return 0;
}

void simon(int n)
{
cout<<"现在整数是:"<<n<<"测试!"<<endl;
}

===========================

【转】Visual Studio 非常实用的调试技巧的更多相关文章

  1. 【Visual Studio】VS常用调试技巧——笔记

    CSDN的文档: https://msdn.microsoft.com/en-us/library/aa295838(v=vs.60).aspx 情景一:[监视]变量时,当运行离开当前函数后,怎么看到 ...

  2. Visual Studio 2012的开发使用技巧

    分享10条Visual Studio 2012的开发使用技巧 使用Visual Studio 2012有一段时间了,并不是追赶潮流,而是被逼迫无可奈何.客户要求的ASP.NET MVC 4的项目,要用 ...

  3. 2.[WP Developer体验Andriod开发]Andriod Studio结合Visual Studio Emulator for Android调试Android App

    0. 工欲善其事必先利其器 上一篇博客对比了一下Android和WinPhnoe的布局容器,后续篇章重点放在Android的开发上了. 说到开发就绕不开调试程序,调试Android App我们有2种选 ...

  4. Visual Studio 2017 通过SSH 调试Linux 上.NET Core

    Visual Studio 2017 通过SSH 调试Linux 上.NET Core 应用程序. 本文环境 开发环境:Win10 x64 Visual Studio 2017 部署环境:Ubuntu ...

  5. 2.[Andriod]Andriod Studio结合Visual Studio Emulator for Android调试Android App

    0. 工欲善其事必先利其器 上一篇博客对比了一下Android和WinPhnoe的布局容器,后续篇章重点放在Android的开发上了. 说到开发就绕不开调试程序,调试Android App我们有2种选 ...

  6. Visual Studio 2010无法启动调试

    现象:Visual Studio 2010点击调试或者按F5.Visual Studio 2010没有什么反应,但又不报错. 而点击运行不调试(Ctrl+F5)却没有问题. 解决的方法:打开项目属性, ...

  7. 实用Javascript调试技巧

    摘要: 高效调试JS代码. 原文:实用Javascript调试技巧分享 作者:MudOnTire Fundebug经授权转载,版权归原作者所有. 见过太多同学调试Javascript只会用简单的con ...

  8. Visual C++ 开发心得与调试技巧

    自己平时收集的一些技巧与心得,这里分享出来,普及一下知识. 1.如何在Release状态下进行调试 Project->Setting=>ProjectSetting对话框,选择Releas ...

  9. 在Visual Studio中快速启动调试Web应用程序

    原文:http://blog.csdn.net/effun/article/details/2638535 到2005,Visual Studio在启动调试的功能上进行了一些改善,不过因为只是简单的一 ...

随机推荐

  1. IDL中histogram的应用

    前面一段时间在使用Histogram时一直是不能更好的理解其中的奥秘,通过阅读帮助以及查看相应的文档,终于理解了其中的玄机,很多时候是因为在学习的时候英文不知道翻译成什么样的内容比较合理,这样就给后面 ...

  2. AssetBundle系列——打包前进行平台检测

    在生成AssetBundle的时候,如果目标平台和当前平台不一致,Unity3D会自动将当前平台转换为目标平台. 如果项目中资源量比较大,这个转换过程是相当漫长的,并且不能够强行中止. 所以最好在Bu ...

  3. 浏览器 Pointer Events

    前言 Pointer Events是一套触控输入处理规格,支持Pointer Events的浏览器包括了IE和Firefox,最近Chrome也宣布即将支持该处理规则. PointerEvent Po ...

  4. Google Kubernetes设计文档之服务篇-转

    摘要:Kubernetes是Google开源的容器集群管理系统,构建于Docker之上,为容器化的应用提供资源调度.部署运行.服务发现.扩容缩容等功能. Pod是创建.调度和管理的最小部署单位,本文详 ...

  5. hash函数为什么要选择对素数求余?

    常用的hash函数是选一个数m取模(余数),这个数在课本中推荐m是素数,但是经常见到选择m=2^n,因为对2^n求余数更快,并认为在key分布均匀的情况下,key%m也是在[0,m-1]区间均匀分布的 ...

  6. 手把手教你从购买vps到搭建一个node服务器

    要准备什么? 1.5刀 2.最好有FQ软件(可以用蓝灯) let's Go! 一.vps购买 vps可以选择digital ocean(do) 链接 ,由于是外国网站,响应比较慢,所以最好翻个墙. g ...

  7. notepad++ 各类插件学习记录

    js文件的规范格式排列: 插件里安装 jstools, 然后重启notepad++再去插件里面的jstool里面用jsformat就可以格式化排列不规则的js代码了 notepad++ 自动补全: 在 ...

  8. 重构第20天 提取子类(Extact SubClass)

    理解:提取子类就是把基类中,不是所有子类或者只有少数子类用到的方法,提取出来,调整到子类中去. 详解:下面的代码中我们用到一个单一的类Registration,来处理学生选课信息. public cl ...

  9. 轻松解决MYSQL数据库连接过多的错误

    1.数据库系统允许的最大可连接数max_connections.这个参数是可以设置的.如果不设置,默认是100.最大是16384. 2.数据库当前的连接线程数threads_connected.这是动 ...

  10. 关于VS2010中的TraceDebugging文件夹浅说

    最近一段时间发现C盘莫名其妙的变小了,各种清理各种卸载还是没有.最后只能一个文件夹一个文件夹的找,最后针对“C:\ProgramData”(win7系统)文件夹,发现这个文件夹有3.9GB大小.然后一 ...