0

0

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

高洛峰

高洛峰

发布时间:2017-02-07 10:56:01

|

1752人浏览过

|

来源于php中文网

原创

这篇文章只介绍了一些有关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弹出对话框,你可以指定原生的(或者托管的)异常,除了调试器自带的一些默认异常,你还可以添加自己的自定义异常。 

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

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

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

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

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

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

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

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

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

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

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

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

技巧4:查看数组的值 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

创客贴设计
创客贴设计

创客贴设计,一款智能在线设计工具,设计不求人,AI助你零基础完成专业设计!

下载
void break_for_debugging() {
__debugbreak();
}

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

__asm int 3;

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

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

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

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

技巧7:在output窗口打印 

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

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

技巧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)就可以识别内存泄漏的起因。 

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

技巧9:调试发行版 

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

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

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

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

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

技巧10:远程调试 

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

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

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

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

远程和本地机器上的防火墙必须允许Visual Studio和远程调试监控之间能够通信

想要调试,PDB文件是关键;为了能够让VisualStudio自动加载它们,必须满足以下条件:

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

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

结束语 

Ivan Shcherbakov那篇文章和我这篇文章提到的调试技巧,在大多数的调试问题中都是必不可少的。

更多分享Visual Studio原生开发的10个调试技巧相关文章请关注PHP中文网!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法
包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法

本专题汇总了包子漫画官网和网页版入口,提供最新章节抢先看方法、正版免费阅读指南,以及稳定访问方式,帮助用户快速直达包子漫画页面,无广告畅享全集漫画内容。

47

2026.02.10

MC.JS网页版快速畅玩指南_MC.JS官网在线入口及免安装体验方法
MC.JS网页版快速畅玩指南_MC.JS官网在线入口及免安装体验方法

本专题汇总了MC.JS官网入口和网页版快速畅玩方法,提供免安装访问、不同版本(1.8.8、1.12.8)在线体验指南,以及正版网页端操作说明,帮助玩家轻松进入MC.JS世界,实现即时畅玩与高效体验。

34

2026.02.10

谷歌邮箱网页版登录与注册全指南_Gmail账号快速访问与安全操作教程
谷歌邮箱网页版登录与注册全指南_Gmail账号快速访问与安全操作教程

本专题汇总了谷歌邮箱网页版的最新登录入口和注册方法,详细提供官方账号快速访问方式、网页版操作教程及安全登录技巧,帮助用户轻松管理Gmail邮箱账户,实现高效、安全的邮箱使用体验。

25

2026.02.10

铁路12306订票与退改全攻略_高效购票与座位选取技巧
铁路12306订票与退改全攻略_高效购票与座位选取技巧

本专题全面汇总铁路12306订票、退票、改签及候补订单操作技巧,提供车厢座位分布参考、抢票攻略和高铁安检注意事项,帮助新手用户快速掌握高效购票与退改流程,提高出行效率和体验。

31

2026.02.10

TensorFlow2深度学习模型实战与优化
TensorFlow2深度学习模型实战与优化

本专题面向 AI 与数据科学开发者,系统讲解 TensorFlow 2 框架下深度学习模型的构建、训练、调优与部署。内容包括神经网络基础、卷积神经网络、循环神经网络、优化算法及模型性能提升技巧。通过实战项目演示,帮助开发者掌握从模型设计到上线的完整流程。

0

2026.02.10

Vue3组合式API与组件开发实战
Vue3组合式API与组件开发实战

本专题讲解 Vue 3 组合式 API 的核心概念与应用技巧,深入分析响应式系统、生命周期管理、组件设计与复用策略。通过完整项目案例,指导前端开发者实现高性能、结构清晰的 Vue 应用,提升开发效率与代码可维护性。

4

2026.02.10

Go语言微服务架构与gRPC实战
Go语言微服务架构与gRPC实战

本专题面向有 Go 基础的开发者,系统讲解微服务架构设计与 gRPC 的高效应用。内容涵盖服务拆分、RPC 通信、负载均衡、错误处理、服务注册与发现等关键技术。通过实战案例,帮助开发者搭建高性能、可扩展的 Go 微服务系统。

1

2026.02.10

React 18状态管理与Hooks高级实践
React 18状态管理与Hooks高级实践

本专题专注于 React 18 的高级开发技术,详细讲解 useState、useEffect、useReducer、useContext 等 Hooks 的使用技巧,以及 Redux、Zustand 等状态管理工具的集成与优化方法。通过真实案例,帮助前端开发者构建可维护、性能优良的现代 React 应用。

4

2026.02.10

Node.js后端开发与Express框架实践
Node.js后端开发与Express框架实践

本专题针对初中级 Node.js 开发者,系统讲解如何使用 Express 框架搭建高性能后端服务。内容包括路由设计、中间件开发、数据库集成、API 安全与异常处理,以及 RESTful API 的设计与优化。通过实际项目演示,帮助开发者快速掌握 Node.js 后端开发流程。

2

2026.02.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号