VC的常用调试方法
前言
VS是非常强大的IDE,所以掌握VSVC的常用方法,将会使得我们找出问题解决问题事半功倍。
目录
- Watch窗口查看伪变量
按MSDN的介绍,伪变量就是用来查看特定信息的术语。例如当调用的API失败时,可以用GetLastError获取对应的错误码。然而,很多时候我们不可能随时修改代码来查看当前错误码。这个时候就可以通过伪变量快速在Watch窗口查看当前错误码了。

常用的一些伪变量有:
- $tid – 当前线程的的线程ID
- $pid – 进程ID
- $cmdline – 附加进程的命令行字符串
- $user – 运行在程序中的帐户信息
- $registername – 显示指定寄存器的寄存器内容
- $err – 显示最近错误的错误码
- $err, hr – 显示最近错误的消息
注:@err,err均可以正确使用。
详情参考:https://msdn.microsoft.com/en-us/library/ms164891.aspx
- 查看指针指向的一序列值
例如有1个int类型的Buff指针pnBuff,我们想查看它的一系列值。很多时候,大家都是使用Memory窗口来查看整片数据。Int类型每隔4个BYTE一个,查看起来非常不方便。如果能够像查看数组一样,在Watch窗口是展开查看就非常方便了。
如果你工作在1个展开在Watch中的大数组(至少几百个元素,但是可能更少)然后去查找一些特定范围的元素将是难以处理的。因为你必须大量滚动。但是如果这个数组是分配在堆上,你甚至都不能在Watch窗口中展开它的元素。这里有1个关于那个问题的解决方案。你能够用语法(array + <offset>), <count>去查看特定范围<count> 开始于<offset>位置(你的真实对象的源数组)。如果你想查看全部的数组,你能够简单的使用rray, <count>。

如果你的数组是在堆上,那么你能够在Watch窗口里将它展开,但是要查看1个特定范围,你必须用一个稍微不同的语法: ((T*)array + <offset>), <count>(注意这个语法对在堆上的多维数组也有效)。在这种情况下,T是这种数组的元素的类型。

如果你工作在MFC下并用来自于其中的"array"容器,像CArray,CDWordArray,CStringArray,等等。你当然能够应用这相同的筛选,除此之外你必须查看array的成员变量m_pData,它是拥有数据的真实缓存。

- 内存泄露查找
VS在调试结束退出时,如果有内存泄露,会在output窗口中显示出相应的信息,很多这些信息会直接指出未释放内存的位置,但有的时候却并未直接指出,这个时候就需要些其他的方法来解决了。
例如Output窗口信息如下:
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
Object dump complete.
方法一,上面{341}的意思是代码第341次分配内存的内存。如果代码没有随机性,这个数字是不会改变的。那么我们可以在当前代码模块的最开始的位置,添加_CrtSetBreakAlloc(341),就表示代码将中断在第341次内存分配的地方,然后再通过Call Stack窗口找到具体的代码位置。
方法二,使用第三方工具,如Visual Leak Detector。下载安装,然后在你觉得最可能导致内存泄露的模块代码里,加上#include <vld.h>即可。如果有stdafx.h,#include <vld.h>直接放在这个文件里也是可以的。然后编译,调试运行,退出,然后就会在Output窗口里显示内存泄露的有关详细信息。
- 调试Release版本
Release版本和Debug版本的主要差别,前者代码编译做了优化,并且一些未初始的临时变量,内存等的值可能是随机的;后者即没有做代码优化,并且未初始化的临时变量默认赋值为0xCCCCCCCC,如果是堆上的内存则默认为0xCDCDCDCD。正因为这两者的不同,可能导致Debug下运行正常,而Release下运行错误的问题。这个时候可能就需要在Release下来进行调试。方法很简单,只需要在Release下关闭优化,并打开调试信息的生成即可。
- C/C++ > Optimization > Optimization should be "Disabled (/Od)"
- Linker > Debugging > Generate Debug Info should be "Yes (/DEBUG)"
详情参考:https://msdn.microsoft.com/en-us/library/fsk896zz.aspx
- 远程调试
如果能够用打印调试信息解决问题的,就尽量不要使用远程调试了。感觉远程调试,总是容易出各种问题。但有的时候还必须得使用远程调试,所以在此简单介绍下。
- 将本地电脑上的Debug程序及相应的PDB文件一起拷贝到远程电脑,注意Debug版程序与PDB文件对应关系和本地电脑保持一致。
- 将VS目录里的Debugging Monitor拷贝到远程电脑上。以管理员身份打开Debugging Monitor,设置为无用户访问模式,并记住服务的名字。


- 打开本地电脑的VS,点击Tool\Attach to Process,启动如下窗口,并在Qualifier中填上远程电脑上Debugging Monitor上的服务名。

详情参考:https://msdn.microsoft.com/en-us/vstudio/aa569599.aspx
- 函数断点
函数断点,我们经常用,鼠标移到某一行,按下F9,即设置了最普通的断点。断点还有很多高级功能,熟练掌握,能够让我们调试更方便。
- 条件断点,条件只要是表达式即可。

- 触发次数断点。

- 过滤断点。

- 数据断点。
断点除了我们常用的函数断点外,再就有的就是数据断点了。在Breakpoints窗口左上角可以选择New Data Breakpoint。

数据断点可以用来查找某个变量在复杂的代码里,究竟是在哪里产生的改变。另外,针对内存覆盖导致的崩溃,用数据断点也是比较方便。内存覆盖导致的崩溃,往往是某个重要变量被影响到了导致的。所以我只要找到重要变量,用数据断点监控起来就可以了。
- 代码执行时间
伪变量中有一个特别的@clk,默认显示系统时钟时间,以毫秒为单位。
在第一次断点时,将@clk放入Watch窗口,并将Value清0.
第二次断点时,@clk对应的Value即为两个断点之间代码的大概执行时间。
- 格式化数据
当你在Watch或Quick Watch窗口查看变量时,这值是用默认的预定义可视化显示的。当它变成数字时,它们是通过它们的类型(整形、浮点、双精度)用十进度制来显示的。但你能够强制让这调试器用不同类型或不同进制或是两者来显示这些数字。
给变量加前缀来改变显示 :
- by 针对无符号字符(又称无符号字节)
- wo 针对无符号短整形 (又称无符号字)
- dw 针对无符号长整形(又称无符号双字)
给变量名加后缀来改变显示:
- , d 或者 , i 针对有符号十进制
- , u 针对无符号十进制
- , o 针对无符号八进制
- , x 针对小写的十六进制或 , X 针对大写的十六进制


- 格式化内存
除了格式化数据,调试器也能在Watch窗口中显示格式化的内存值,高达64个字节。你能用下面的说明符在表达式(变量或内存地址)后来格式化数据。
- mb / m - BYTE
- mw - WORD
- md - DWORD
- mq – 8BYTE
- ma – 16BYTE
- mu – 2BYTE UNICODE characters

- 其他
一段代码进入死循环,如何快速找到在哪里呢?直接点击
中断所有。
应用程序打开异常,调用DLL异常,使用dependens.exe。
VC的常用调试方法的更多相关文章
- shell 脚本常用调试方法
曾经我刚开始学习 shell 脚本时,除了知道用 echo 输出一些信息外,并不知道其他方法,仅仅依赖 echo 来查找错误,比较难调试且过程繁琐.效率低下.本文介绍下我常用的一些 shell 脚本调 ...
- iPhone页面的常用调试方法
在iPhone中调试,大体上与上文 安卓中的移动页面调试 类似,区别主要是iOS系统中的一些限制,导致某些工具无法使用. 本文基于此,简要介绍在iPhone中如何调试页面. 最终可以实现在Mac平台使 ...
- 【转】 GDB 常用调试方法
一.多线程调试 多线程调试可能是问得最多的.其实,重要就是下面几个命令: info thread 查看当前进程的线程. thread <ID> 切换调试的线程为指定ID的线程. break ...
- onvif规范的实现:onvif开发常用调试方法 和常见的segmentation fault错误
在前几篇中,虽然已经实现了rtsp视频流的对接,但是还要做的工作还非常多,onvif本来就是一个覆盖面非常广的一个协议,每一个功能都要填充大量的函数.而且稍不注意就会出现segmentation fa ...
- Makefile常用调试方法
转载自 陈皓<跟我一起写 Makefile><GNU Make项目管理> GNU make 提供了若干可以协助调试的内置函数以及命令行选项. 1.warning函数 $(war ...
- shell常用调试方法
检查语法 -n选项只做语法检查,而不执行脚本. sh -n script_name.sh 启动调试 sh -x script_name.s 进入调试模式后,Shell依次执行读入的语句,产生的输出中有 ...
- sqlprofiler 常用调试方法
- VC调试方法大全
VC调试方法大全 一.调试基础 调试快捷键 F5: 开始调试 Shift+F5: 停止调试 F10: 调试到下一句,这里是单步跟踪 F11: 调试到下一句,跟进函数内部 Shift+F11: ...
- eclipse 常用快捷键及调试方法
原文链接:http://my.oschina.net/u/1054538/blog/741561 常用快捷键 Eclipse最全快捷键,熟悉快捷键可以帮助开发事半功倍,节省更多的时间来用于做有意义的事 ...
随机推荐
- C语言用一级指针处理字符串的反思
1.一级指针处理字符串的常见方式 如果使用单个指针,不方便对字符串本身进行操作,只适合遍历. 使用两个指针, 两个指针和字符串大致有两个常见处理方式: (1)两个指针从字符串首部开始向后移动,同时处理 ...
- Altera三速以太网IP核快速仿真与使用(上篇)
对于比较高级的ip核,altera一般都会提供仿真案例,网上有关于这个IP核的各种仿真方法,但都比较繁琐,前几日,朋友跟我分享了一个比较快速高效的仿真方法,这个方法也是他摸索折腾了一段时间才总结出来的 ...
- 20155220吴思其 实验2 Windows口令破解
实验目的: 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验人数 每组一人 系统环境 windows 实验工具 LC5 SuperDic 实验原理 口令破解方法 ...
- 20155230 《Java程序设计》实验五 Java网络编程及安全
20155230 <Java程序设计>实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验1 两人一组结对编程 ...
- 20155301 2016-2017-2 《Java程序设计》第10周学习总结
20155301 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 计算机网络: 1.在计算机网络中,现在命名IP地址的规定是IPv4协议,该协议规定每个IP ...
- 单线程的redis为什么吞吐量可以这么大
原文:单线程的redis为什么吞吐量可以这么大 一.Redis的高并发和快速原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了很多上下文切换线程的时间: 3.r ...
- python全栈开发-前方高能-内置函数2
python_day_15 一.今日主要内容 1. lambda 匿名函数 语法: lambda 参数:返回值 不能完成复杂的操作 2. sorted() 函数 排序. 1. 可迭代对象 2. key ...
- maven 手动安装jar包
1.问题 maven有时候在pom文件引入jar包会报错,所以可以通过手动导入jar包的方式导入. 2.解决: 通过maven命令导入jar包, mvn install:install-file -D ...
- 视觉SLAM中的深度估计问题
一.研究背景 视觉SLAM需要获取世界坐标系中点的深度. 世界坐标系到像素坐标系的转换为(深度即Z): 深度的获取一共分两种方式: a)主动式 RGB-D相机按照原理又分为结构光测距.ToF相机 To ...
- 【转】微信小程序实现自动化测试
山雨欲来风满楼,最近微信小程序相关开发文章吹遍大江南北,亦有摧枯拉朽万象更新之势.问小程序形为何物,直教IT众生怡情悦性高潮迭起.作为一名有着远大理想“包袱”与互联网变革 “使命感”的测试工程师,我再 ...