分享Visual Studio原生开发的10个调试技巧

最近碰巧读了Ivan Shcherbakov写的一篇文章,《11个强大的Visual Studio调试小技巧》。这篇文章只介绍了一些有关Visual Studio的基本调试技巧,但是还有其他一些同样有用的技巧。我整理了一些Visual Studio(至少在VS 2008下)原生开发的调试技巧。(如果你是工作在托管代码下,调试器会有更多的特性,在CodeProject中有介绍它们的文章),下面是我的整理的一些技巧:

异常中断 | Break on Exception
Watch窗口中的伪变量 | Pseudo-variables in Watch Windows
符号越界后查看堆对象 |
查看数组的值
避免进入不必要的函数
从代码启动调试器 | Launch the debugger from code
在Output窗口打印
隔离内存泄漏
调试发行版 | Debug the Release Build
远程调试

技巧1: 异常中断

在处理被调用之前,异常发生时可以 启动调试器进行中断,可以让你在异常发生后立即调试程序。操作调用栈便于你去查找异常发生的根本原因。

Vistual Studio允许你去指定想要中断的异常类型或者特殊异常。选择菜单Debug>Exceptions弹出对话框,你可以指定原生的(或者托管的)异常,除了调试器自带的一些默认异常,你还可以添加自己的自定义异常。

下面是一个std::exception 异常抛出时调试器中断的例子。

更多阅读:

技巧2:Watch窗口中的伪变量

Watch窗口或QuickWatch对话框提供一些特定的(调试器可识别的)变量,被称为伪变量。文档包含以下:

$tid—–当前线程的线程ID
$pid——进程ID
$cmdline———-启动程序的命令行字符串
$user———-正在运行程序的账户信息
$registername—–显示寄存器registername 的内容
不管怎么样,关于最后一个错误的伪变量是非常有用的:

$err——–显示最后一个错误的错误码
$err,hr—显示最后一个错误的错误信息

更多阅读:伪变量

技巧3:符合越界后查看堆对象

有时候,在调试符号越界后,你还想查看对象的值,这个时候,watch窗口中的变量是被禁用的,不能再查看(也不能更新),尽管对象仍然存在。你如果知道对象的地址,可以继续充分地观察它。你可以将地址转换为该对象类型的指针,放在watch窗中。

下面的例子中,当单步跳出do_foo()之后,_foo不能再被访问。但是,将它的地址转换为foo*后,就可以继续观察这个对象。

技巧4:查看数组的值

如果你在操作一个很大的数组(我们假设至少有几百个元素吧,但是可能更少),在Watch窗口中展开数组,查找一些特定范围内的元素很麻烦,因为你要不停地滚动.如果数组是分配在堆上的话,你甚至不能在watch窗口中展开数组元素.对此,有一个解决办法。你可以使用(array+ <offset>),<count> 去查看从<offset>位置开始的特定范围的<count>元素(当然,这儿的数组是你的实际对象)。如果想查看整个数组,可以简单使用array,<count>.

如果你的数组是在堆上,你可以在watch窗口中将它展开,但是要查看某个特定范围的值,用法稍有不同:((T*) array + <offset>),<count>(注意这种用法对于堆上的多维数组也有效)。但是这种情况下,T是指数组元素的类型。

如果你在用MFC,并使用其中的'array'容器,像 CArray, CDWordArray,CStringArray等等。你当然可以使用同样的过滤方法。除此之外,你必须查看array的m_pData成员,它是保存数据的真实缓存。

技巧5:避免进入不必要的函数

很多时候,你在调试代码时可能会进入到你想跳过的函数,像构造函数,赋值操作或者其他的。其中最困扰我的是CString构造函数。下面是一个例子,当你准备单步执行take_a_string()函数时,首先进入到CString的构造函数。

void take_a_string(CString const &text){}void test_string(){ take_a_string(_T("sample"));}


幸运的是可以告诉调试器去跳过哪些方法,类或者整个命名空间。实现它的方法也已经改变了,回到使用VS6的日子,通常是通过autoexp.dat文件来指定的。Vistual Studio 2002改成了使用注册表设置。想要跳过一些函数,你需要在注册表里添加一些值(详情如下):

    实际位置取决于你使用的Vistual Studio版本和操作系统平台(x86或x64,因为注册表只能在64位的Windows下浏览)值的名字是数字,代表规则的优先级;数字越大,优先级越高。值数据是一个正则表达式的REG_SZ值,用于指定怎样过滤和执行。

为了避免进入任何CString方法,我添加了下面的规则:

有了这个,即使你强制进入上例中的take_a_string(),调试器也会跳过CString的构造函数。

更多阅读:

技巧6:从代码启动调试器 Launch the debugger from code

你可能很少需要将调试器附加到程序中,但你不能在Attach窗口这样做(可能因为中断发生太快而没有捕获到),你也不能一开始就在调试器中启动程序。你可以在程序中产生中断给调试器一个机会通过调用内部的_degbugbreak()来附加。

代码如下:

void break_for_debugging() {
__debugbreak();
}

实际上还有其他的方法来完成,例如触发中断3,但这仅仅适用于x86平台(C++64位不再支持ASM)。另外还有DebugBreak()函数,但它的使用不怎么简便,所以这里推荐使用内部方法。

代码如下:

__asm int 3;

程序运行内部方法时会停止运行,这时你就有机会将调试器附加到该进程。

更多阅读:

技巧7:在output窗口打印

通过调用DebugOutputString可以在调试器的output窗口显示一段特定的文本。如果没有附加的调试器,该函数什么也不做。

更多阅读:

技巧8:隔离内存泄漏

内存泄漏是在原生开发中的一个很重要的问题,要检测内存泄漏是一个很严峻的挑战,尤其是在大型项目中。Vistual Studio可以提供检测内存泄漏的报告,还有其他的一些应用程序(免费的或商业的)也可以帮助你检测内存泄漏.有些情况下,在一些内存分配最终会导致泄漏时,可以使用调试器去中断。但是你必须找到可再现的分配编号(尽管没那么容易)。如果能做到这一点,执行程序时调试器才会中断。

我们来看下面的代码,分配了8个字节,却一直没释放分配的内存。Visual Studio提供了造成内存泄漏的对象的报告,多运行几次,会发现一直是同一个分配编号(341)。

代码如下:

void leak_some_memory()
{
char* buffer = new char[8];
}
Dumping objects ->
d:\marius\vc++\debuggingdemos\debuggingdemos.cpp(103) : {341} normal block at 0x00F71F38, 8 bytes long.
Data: < > CD CD CD CD CD CD CD CD

在一个特定的(可复现的)位置中断的步骤如下:

确定你有足够的关于内存泄漏的报告模式(参考 使用CRT库检测内存泄漏)
多次运行程序直到你能在程序运行结束后的内存泄漏报告里找到一个可复现的分配编号,例如上个例子中的(341)
在程序一开始的地方设置一个断点以便你能够尽早地进行中断。
当最初的中断发生时,watch窗口的Name栏里会显示:{,,msvcr90d.dll}_crtBreakAlloc,在Value栏里写入你想要查找的位置编号
继续调试(F5)
程序执行到指定位置会停止,你可以使用调用栈被指引找到被该位置触发的那段代码。
遵循这些步骤, 在上个例子中,使用分配的编号(341)就可以识别内存泄漏的起因。

技巧9:调试发行版

调试和发布是两个不同的目的。调试配置是用于开发的,而发布配置,顾名思义,是用来作为程序的最终版本,因为它必须严格遵循发布的质量要求,该配置包含优化部分和调试版本的中断调试的设置。而且,有时候,要像调试调试版本一样去调试发行版。要做到这一点,你需要在配置里做一些改变。但是这种情况下,你就不再是在调试发行版,而是调试和发行的混合版。

你还应该做一些事儿,以下是必须要做的:

配置C/C++ >General>Debug Information Format 应该为 “Program Database(/Zi)”
配置C/C++ >Optimization>Optimization 应该为”Disabld(/Od)”
配置Linker>Debugging>Generate Debug Info 应该为”Yes/(DEBUG)”
如图所示:

更多阅读:怎样调试发行版

技巧10:远程调试

另一个重要的调试就是远程调试,这是一个更大的话题,多次被提到,这里我只做一下简单的概括:

你需要在远程机器上安装远程调试监控
远程调试监控必须以管理员身份运行,并且用户必须属于管理员组
在你运行监控时,会开启一个新的服务,该服务的名字必须用Visual Studio的Attach to Progress窗口的Qualifier组合框的值。

  1. 远程和本地机器上的防火墙必须允许Visual Studio和远程调试监控之间能够通信
  2. 想要调试,PDB文件是关键;为了能够让VisualStudio自动加载它们,必须满足以下条件:

1)本地的PDB文件必须可用(在远程机器的相同路径下放置一个对应的模块)。

2) 远程机器上的托管PDB文化必须可用。

远程调试监控下载:

更多阅读:

结束语

Ivan Shcherbakov那篇文章和我这篇文章提到的调试技巧,在大多数的调试问题中都是必不可少的。想要知道更多的关于调试技巧的知识,建议阅读文章中提供的额外阅读。

原文链接: Marius Bancila   翻译: 伯乐在线- 伯乐在线读者
译文链接: http://blog.jobbole.com/45249/

(0)

相关推荐

  • 配置Visual Studio 以调试.net framework源代码第1/2页

    基本步骤注意,这个功能在Visual Studio 2008 Express版里不支持.1)安装Visual Studio 2008 QFE.这个QFE只是更新一个Visual Studio调试器的DLL,以便可以获取源代码,更多细节参加下载页面.2)运行Visual Studio 2008依次展开Tools->Options->Debugging->General.如果你在Visual Basic Profile环境下运行,你需要将lower left of the Options D

  • 分享Visual Studio原生开发的10个调试技巧(2)

    之前关于Visual Studio调试技巧的文章引起了大家很大的兴趣,以至于我决定分享更多调试的知识.以下的列表中你可以看到写原生开发的调试技巧(接着以前的文章来编号).这些技巧可以应用在VS2005或者更新版本中(当然有一些可以适用于旧版本).如果你继续,你可以知道每个技巧的详细信息. 技巧11:数据断点 当数据所在内存位置变化时,调试器将会中断.然而,这是唯一可能在一个时间创建4这样的硬件的数据断点.数据断点只能在编译的过程中添加,可以通过菜单(编译>新断点>新数据断点)或者通过断点窗口来

  • Visual Studio调试技巧汇总

    调试是软件开发周期中很重要的一部分.它具有挑战性,同时也很让人疑惑和烦恼.总的来说,对于稍大一点的程序,调试是不可避免的.最近几年,调试工具的发展让很多调试任务变的越来越简单和省时. 1 悬停鼠标查看表达式值 调试是很有挑战性的.比如在函数内逐步运行可以看出哪里出错,查看堆栈信息可以知道函数被谁调用等等. 但是无论哪种情况下,查看表达式和局部变量的值都是很麻烦的(把表达式和局部变量放到watch窗口里). 一种更简单的方法,把鼠标停在所需查看的数据上.如果是类或结构,那么点击展开可以很方便快速地

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

    Visual Studio 2017 通过SSH 调试Linux 上.NET Core 应用程序. 本文环境 开发环境:Win10 x64 Visual Studio 2017 部署环境:Ubuntu 14.04 x64 .NET Core SDK 1.0.1 Ubuntu上安装.NET Core SDK Ubuntu 14.04 x64 sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotn

  • Visual Studio Debugger七个鲜为人知的小功能

    Visual Studio debugger是一个很棒的调试工具,可以帮助程序猿们快速地发现和解决问题.这里给大家简单介绍一下VS调试工具中的七个鲜为人知的小功能. 1. 一键跳转到指定语句 调试过程中经常需要拖拽黄箭头,使特定语句执行或者不执行.常规方法就是使用鼠标直接拖拽. 在Visual Studio 2017 15.3预览版中,有一个更简单地跳转到目标行的方法:在目标行盘旋鼠标指针,出现绿色竖线右箭头图标后,按住CTRL后鼠标左键点击,就把调试黄箭头移过去了,再点击调试下一步或者F5就直

  • Visual Studio中js调试的方法图解

    第一步:在需要打断点处写上 debugger; 第二部:在IE中将禁用脚本调试的钩去掉 打开IE -> 工具 -> 选项 -> 高级 -> 去掉禁用脚本调试(Internet Explorer)和禁用脚本调试(其他) 不用调试时记得将IE去掉的钩,钩上,以免打开其它网页报错!

  • 解决Visual Studio 2012 Update 4 RC启动调试失败的方案

    本教程就是帮助大家解决Visual Studio 2012 Update 4 RC启动调试失败的问题,具体内容如下 以下解决办法适用于任何Visual Studio开发环境,及Windows NT 6.1以上系统. 系统:Windows 8.1 Enterprisex64 RTM 开发环境:Visual Studio 2012 Update 4 RC 运行库:.NET Framework 4.5 x64 承载环境:IIS 8.0 错误:无法在web服务器上启动调试,您没有调试web服务器进程的权

  • 使用Fiddler调试visual studion多个虚拟站点的问题分析

    1:localhost.和127.0.0.1.带来的URL行为不一致 无法走本地代理,这个无法本地调试的问题并不是个BUG,微软官方是有给出过解释的,这是源于IE浏览器和.NET框架对于本地请求是不走代理的,因而Fiddler无法检测数据.于是为本地地址加.符号,这就带来URL行为不一致的问题. 取当前Context.Request.URL,会发现系统自动将地址中的.符号忽略了,这为我们针对URL编码带来了不一致的问题: 2:target machine actively refused it(

  • 分享Visual Studio原生开发的10个调试技巧

    最近碰巧读了Ivan Shcherbakov写的一篇文章,<11个强大的Visual Studio调试小技巧>.这篇文章只介绍了一些有关Visual Studio的基本调试技巧,但是还有其他一些同样有用的技巧.我整理了一些Visual Studio(至少在VS 2008下)原生开发的调试技巧.(如果你是工作在托管代码下,调试器会有更多的特性,在CodeProject中有介绍它们的文章),下面是我的整理的一些技巧: 异常中断 | Break on Exception Watch窗口中的伪变量 |

  • 最锋利的Visual Studio Web开发工具扩展:Web Essentials使用详解

    首先,从Extension Manager里安装:最新版本是19号发布的2.5版 然后重启你的VS开发环境,就可以使用它提供的方便功能了. Web Essentials对CSS.JavaScript和HTML都提供了很多快捷的功能支持,具体列表如下: CSS 即时预览Live Web Preview 每次修改的时候,都可以使用CTRL+ALT+Enter快捷键或者点击方案右键上的Live Web Preview选项来即时预览你修改的页面,每次修改完 HTML或者相应的CSS, Ctrl+S保存以

  • Visual Studio 2017开发环境的安装图文教程

    Visual Studio 2017是微软为了配合.NET战略推出的IDE开发环境,同时也是目前开发C#程序最新的工具,本节以Visual Studio 2017社区版的安装为例讲解具体的安装步骤. 说明:Visual Studio 2017 社区版是完全免费的,其下载地址为:https://www.visualstudio.com/zh-hans/downloads/ . 安装Visual Studio 2017社区版的步骤如下: (1)Visual Studio 2017社区版的安装文件是e

  • 使用 Visual Studio 2022 开发 Linux C++ 应用程序的过程详解

    使用 Visual Studio 2022 开发 Linux C++ 应用程序 使用 Visual Studio 2022 with WSL2 ! Visual Studio 2022 引入了用于 Linux C++ 开发的本机 WSL2 工具集,可以构建和调试 Linux C++ 代码,并提供了非常好的 Linux 文件系统性能.GUI 支持和完整的系统调用兼容性. CMake 是对使用 Visual Studio 2022 的 C++ 跨平台应用开发的推荐,因为它允许在 Windows.WS

  • 使用Visual Studio 2022开发前端的详细教程

    目录 创建宿主项目 安装前端库 在浏览器引入模块 模块化开发 前端开发环境多数基于Node.js,好处不多说了.但与使用Visual Studio开发的后端Asp.Net Core项目一起调试,却不是很方便,所以试着在Visual Studio 2022中开发前端. 创建宿主项目 首先创建一个空的Asp.Net Core项目作为宿主,创建完成后将Program.cs中的代码修改如下: var builder = WebApplication.CreateBuilder(args); var ap

  • Visual Studio 2022使用MinGW来编译调试C/C++程序的图文教程

    目录 一.创建项目 二.配置CMake 三.配置调试 Visual Studio的新版本已经可以像VSCode一样创建CMake项目了,但是默认的情况下是使用的Visual Studio编译器及调试器不包括MinGW中的工具集,参见下面的默认可选工具集: 本文就以实例来简单介绍一下VS2022中如何使用MinGW来编译.调试C/C++程序. 一.创建项目 首先,创建一个新项目: 然后,选择CMake项目: 填写项目名称,比如test 项目创建好后如下所示,由于笔者并未安装VS的Windows C

  • Visual Studio快速开发以及Visual Studio 2010新功能介绍

    1.快捷命令: 复制代码 代码如下: "devenv" 启动相应版本的 Visual Studio "Inetmgr" IIS 管理器,不用到管理里去找了,很快就可以显示 IIS管理了 2.集成开发环境(IDE) 复制代码 代码如下: vs2010 的 IDE 已经过重新设计,提高了可性读. 为了减少杂乱,不必要的行和渐变都已删除 安装Visual Studio 后第一次加载需要选择默认的集成开发环境 (IDE),根据项目选择,一般选Visual C#开发, 如果在

  • Visual Studio 2013+OpenCV2.4.10环境搭建教程

    Opencv是一个使用起来非常方便的开放视觉库.本文详细讲解如何在Win8.1+Visual Studio 2013环境下配置Opencv2.4.10 工具:Opencv2.4.10 方法/步骤: 这里用的Opencv版本是2.4.10,可以在Opencv的官网上免费下载.软件大小约为350M. 下载完毕后,双击打开"opencv-2.4.10",选择解压目录.我这里选择解压目录为D盘.确认解压目录后,点击"Extract".解压完成后,在opencv文件夹中生成两

随机推荐