原文链接地址:http://blog.csdn.net/Donjuan/article/details/4649372

讲完Visual Studio调试之断点技巧篇以后,翻翻以前看得一些资料和自己写的一些文章,发现还有几个关于中断程序的技巧在前面的文章里面遗漏了,决定还是在这里总结一下。当然啦,如果你知道这些技巧,忽略这篇文章好了,:)

在程序启动的时候将调试器附加上去

可能有人会对这个问题有一些争议,因为大部分情况下我们只需要在调试器(Debugger)里面直接启动被调试程序(Debuggee)就可以在程序启动前调试程序了。

但有些情况下,你是不能控制被调试程序(Debuggee)在什么时候启动的。例如在DCOM环境里面,DCOM客户端(Client)可以通过调用CoCreateInstanceEx(…, CTX_LOCAL_SERVER, …)启动DCOM服务器(Server),启动DCOM服务器的过程是在COM库中进行的, 你没有办法将在DCOM服务器的WinMain函数之前将你的调试器附加(Attach)上去。Windows提供了一个功能就是在一个程序启动的时候,自动将设置好的调试器附加到这个新启动的程序上去。这里我就是要介绍这个功能:

或者说你需要调试一个Windows服务的启动部分,在服务启动的时候,让调试器附加上去岂不是比在Start()函数里面打印很多跟踪信息要好很多?

在程序启动的时候将调试器附加上去实际上是Windows操作系统提供的功能,呃……当然,调试器之所以能工作,也是CPU和操作系统通力合作的结果,:)。因此你需要修改一些操作系统里面的设置:

1. 打开注册表编辑器(regedit.exe).

2. 找到键值HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Image File Execution Options/。

3. 新建一个键(Key),键名就是你要调试的程序的文件名,例如notepad.exe。

4. 然后在这个新建的键值(Key)下,在我们的例子里,这个键值是notepad.exe。新建一个字符串值(String Value)Debugger,值设置为你喜欢的调试器:

a. 如果选择Visual Studio的话,就是D:/Program Files/Microsoft Visual Studio 9.0/Common7/IDE/devenv.exe(假设你的Visual Studio安装在D盘)

b. 选择Windbg的话,就是c:/debuggers/windbg.exe(假设你的Windbg拷贝在c:/debuggers/目录里)。

设置好了以后,启动notepad.exe,这个时候你选择的调试器就会被Windows先启动起来,然后在notepad.exe的入口处中断。换句话说,所有的程序,都可以使用这种方法在启动的时候自动激活调试器,当然啦,如果你已经修复了你的问题,不需要调试器在程序启动之前启动的话,在注册表里面删掉那个键值就好了。

如何设置验尸调试(POSTMORTEM DEBUGGER)

首先先讲一下什么叫做验尸调试,大家应该都有这个体验,当一个程序突然崩溃的时候,Windows会不失时机弹出一个对话框,问你是否要发送错误报告给微软。其实这个对话框叫做Watson, 是Windows自带的一个非常简单的调试器,它的工作就是将程序的内存拷贝下来保存到一个文件当中。这个过程就是验尸调试的准备步骤,因为程序加载进内存以后,术语叫做进程,当进程崩溃的时候,就是意外死亡嘛,当然进程正常结束那叫做自然死亡。一般我们只对意外死亡的进程比较感兴趣,就跟电视里警匪片里面描写的那样,一个无辜的配角死掉了,警察第一步总是要保护现场,带尸体回去 ,让法医验尸。进程意外死亡的时候,Windows区别进程是否是意外死亡的方式很简单,就是看进程里面是否有未处理的异常。Windows也提供了一个选项,可以让你把犯罪现场--进程发生异常的时候的内存保留下来(进程的尸体),你可以在晚一点的时候来慢慢分析这个内存(比如看一看堆栈,一些变量什么的)--这个过程就叫做验尸。

验尸调试对下面这种情况很有帮助:

1. 重现很难重现的bug,比如说你有一个bug是随机出现,但是每次出现都会把程序搞死,与其绞尽脑汁去回忆重现步骤,还不如直接把犯罪现场保留下来,慢慢分析。

启动非托管程序的验尸调试功能

跟在程序启动时将调试器附加上去类似,验尸调试实际上也是Windows提供的功能,启动验尸调试,你需要修改下面的注册表设置:

在//HKEY_LOCAL_MACHINE/Software/Microsoft/Windows NT/CurrentVersion/AeDebug里面,分别创建下面两个键:

如图所示:

里面的键值说明一下:

  1. Debugger:指定了用来执行验尸调试的调试器文件名的完整路径,-p和-e是调试器的一些命令行参数,而%ld则是一个占位符,Windows会把死亡的进程的PID替换%ld这个值(读者如果熟悉批处理编程的话,就应该知道%ld实际上是批处理程序的参数的声明方式)。vsjitdebugger.exe是Visual Studio用来处理验尸调试的调试器名称,如果你安装了Visual Studio,VS的安装程序应该会自动为你设置好这个键。
  2. Auto:如果值是1的话,那么windows就会自动在进程死亡的时候,启动调试器;如果为0的话,就会打开一个对话框问你是否要执行验尸调试—但是Windows 7如果是这个选项的话,会直接禁用验尸调试,因此我推荐将Auto的值总是设置成1。

备注:对于偏好windbg的读者,你有两个方案将Windbg设置成默认的验尸调试程序:

  1. 直接执行  windbg –I   这个命令,注意I要大写。
  2. 将Debugger的键值设置为:"c:/Debuggers/windbg.exe" -p %ld -e %ld –g

设置好了以后,我们可以写一个测试程序来试一下刚才的设置:

Test.cpp

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])

{

int *p = NULL;

// 触发一个异常

*p = 0;

return 0;

}

使用命令cl.exe /Zi test.cpp编译好程序以后,执行test.exe,你应该就可以看到类似下面的现象了:

启动托管程序的验尸调试功能

然而,上面的设置仅对native程序有效,如果要设置托管程序的默认验尸调试器,在//HKEY_LOCAL_MACHINE/Software/Microsoft/.NETFramework里面,分别创建下面两个键:

使用上面的设置,你应该可以做所有非Winform托管程序的验尸调试了。

启动Winform程序的验尸调试功能

然而,当你的Win form程序崩溃(Crash)的时候,你会发现你设置的默认验尸调试器没有运行起来,原因是因为Win form程序默认禁用了即时调试(JIT Debug)的功能。因此要设置Win form程序的默认验尸调试器,你除了做上面的步骤以外,你还要将Win form程序的即时调试功能打开。打开的方法:

1. 修改你机器的machine.config文件,这样机器上所有的Win form程序都会将这个即时调试功能打开。在<configuration>里面添加下面一行:

<system.windows.forms jitDebugging="true" />

2. 修改单独程序的的app.config文件打开单个Win form程序的即时调试功能。在<configuration>里面添加下面一行:

<system.windows.forms jitDebugging="true" />

例如:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.windows.forms jitDebugging="true" />

</configuration>

使用Visual Studio的RPC调试功能同时调试COM程序的客户端和服务端

参看我以前的文章:

http://blog.csdn.net/Donjuan/archive/2009/01/23/3851586.aspx

Visual Studio调试之断点技巧篇补遗的更多相关文章

  1. Visual Studio调试之断点技巧篇

    原文链接地址:http://blog.csdn.net/Donjuan/article/details/4618717 函数断点 在前面的文章Visual Studio调试之避免单步跟踪调试模式里面我 ...

  2. Visual Studio调试之断点进阶篇

    Visual Studio调试之断点进阶篇 在上一篇文章Visual Studio调试之断点基础篇里面介绍了什么是断点,INT 是Intel系列CPU的一个指令,可以让程序产生一个中断或者异常.程序中 ...

  3. Visual Studio调试之断点基础篇

    Visual Studio调试之断点基础篇 我曾经问过很多人,你一般是怎么调试你的程序的? F9, F5, F11, F…… 有很多书和文章都是介绍怎么使用Visual Studio编写WinForm ...

  4. VISUAL STUDIO 调试

    调试术语 Visual Studio调试之断点基础篇 Visual Studio调试之断点进阶篇 不能设置断点的检查步骤 Visual Studio调试之断点技巧篇 Visual Studio调试之断 ...

  5. Visual Studio调试之避免单步跟踪调试模式

    Visual Studio调试之避免单步跟踪调试模式 写完Visual Studio调试之断点进阶篇之后,想分享一下我常用的一些调试技巧,后面发现写之前,一些背景知识需要介绍一下. 下面是几篇今年2月 ...

  6. Visual Studio调试之符号文件

    原文链接地址:http://www.cnblogs.com/killmyday/archive/2009/10/14/1582882.html 前面在不能设置断点的检查步骤和Visual Studio ...

  7. [转]Visual Studio调试之符号文件

    http://www.cnblogs.com/killmyday/archive/2009/10/14/1582882.html 前面在不能设置断点的检查步骤和Visual Studio调试之断点进阶 ...

  8. 12个Visual Studio调试效率技巧

    在这篇文章中,我们假定读者了解VS基本的调试知识,如: F5 开始使用调试器运行程序 F9 在当前行设置断点 F10 运行到下一个断点处 F5 从被调试的已停止程序恢复执行 F11 步进到函数内(如果 ...

  9. Visual Studio 调试技巧[Command Window & Immediate Window ](Tips)

    Visual Studio 调试技巧[Command Window & Immediate Window ](Tips) 1. immediate window 定义的一些 alias (// ...

随机推荐

  1. Linux之MariaDB

    MariaDB数据库的起源 MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜 ...

  2. phpredis命令

    <?php //redis //检查一个扩展是否已经加载.大小写不敏感. if (!function_exists('redis')) { echo '不支持 redis'; return ; ...

  3. 电子商城实录------定义init初始化的方法

    路由方法的设置 //路由方法 private static function dispatch(){ //获取控制器名称(类比:英文单词的后缀) $controller_name=CONTROLLER ...

  4. 服务器空间不足导致mysql服务器无法运行

    今天有朋友请我帮忙解决一个问题,他公司服务器mysql数据库一直连接失败.登录服务期之后发现服务器空间占满了,导致mysql不能启动. 下面说解决方法: 首先查看空间占用,发现空间占满了 df -h ...

  5. Hadoop(4)--Hbase

    Hadoop 其它组成角色介绍--Hbase 在apache的官方网站上,对于Hbase的定义是他是Hadoop的第一个分布式.可扩展的大数据存储的数据库,他的目标是将非常大的表托管到一个集群中进行相 ...

  6. (数据科学学习手札03)Python与R在随机数生成上的异同

    随机数的使用是很多算法的关键步骤,例如蒙特卡洛法.遗传算法中的轮盘赌法的过程,因此对于任意一种语言,掌握其各类型随机数生成的方法至关重要,Python与R在随机数底层生成上都依靠梅森旋转(twiste ...

  7. [拉格朗日反演][FFT][NTT][多项式大全]详解

    1.多项式的两种表示法 1.系数表示法 我们最常用的多项式表示法就是系数表示法,一个次数界为\(n\)的多项式\(S(x)\)可以用一个向量\(s=(s_0,s_1,s_2,\cdots,s_n-1) ...

  8. shell重温---基础篇(流程控制&if判断&for&while&循环操作)

        和Java.PHP等语言不一样,sh的流程控制不可为空,如(以下为PHP流程控制写法): <?php if (isset($_GET["q"])) { search( ...

  9. Android Stadio 指定文件打开类型

    我们项目里面,有一个文件,叫做aaa.meta. 这个只是一个配置文件,里面是txt. 但是Android Stadio 不识别.怎么办? 设置如下图: 首先,打开Android stadio 的设置 ...

  10. luogu4238 【模板】多项式求逆

    ref #include <iostream> #include <cstdio> using namespace std; typedef long long ll; int ...