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最全快捷键,熟悉快捷键可以帮助开发事半功倍,节省更多的时间来用于做有意义的事 ...
随机推荐
- 从“顶点小说”下载完整小说——python爬虫
此程序只是单纯的为了练习而做,首先这个顶点小说非收费型的那种小说网站(咳咳,我们应该支持正版,正版万岁,✌).经常在这个网站看小说,所以就光荣的选择了这个网站.此外,其实里面是自带下载功能的,而且支持 ...
- Python3 图像识别(一)
Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.环境准备: 1.Python3.x(我是用的是Python3.6.5),这个问题不大,只要3.4以上就OK. ...
- 20155214 2016-2017-2 《Java程序设计》第4周学习总结
20155214 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 Chapter6 父类就是将多个类的相同代码提升(Pull Up) 子类继承父类会继承到pr ...
- 【Windows10】我的电脑从新装到优化配置
[Windows10]我的电脑从新装到优化配置 必装软件 Visual Studio Microsoft VS Code Microsoft Expression Design 4 Notepad2- ...
- L012-linux系统文件属性知识深入详解小结
L012-linux系统文件属性知识深入详解小结 最近的学习重点不在这上面,所以更新的比较慢,再加上母亲住院,感情问题,一系列吧,愿快点度过这黑色的4月份,希望我能在5月份阳光起来,加油! 回归正题 ...
- angular 缓存模板 ng-template $templateCache
由于浏览器加载html模板是异步加载的,如果加载大量的模板会拖慢网站的速度,这里有一个技巧,就是先缓存模板. 使用angular缓存模板主要有三种方法: 方法一:通过script标签引入 <sc ...
- Intellij IDEA 2017 通过scala工程运行wordcount
首先是安装scala插件,可以通过idea内置的自动安装方式进行,也可以手动下载可用的插件包之后再通过idea导入. scala插件安装完成之后,新建scala项目,右侧使用默认的sbt 点击Next ...
- 宿主机 PL/SQL Developer 连接虚拟机 ORACLE 数据库
1.确保主机与虚拟机间通信正常,双方关闭window防火墙.如能 ping 通,请确保两机IP在一个网段 2.主机安装orcl客户端 3.虚拟机 D:\app\lin\product\11.2.0\d ...
- 04-JVM内存模型:直接内存
1.1.什么是直接内存(Derect Memory) 在内存模型最开始的章节中,我们画出了JVM的内存模型,里面并不包含直接内存,也就是说这块内存区域并不是JVM运行时数据区的一部分,但它却会被频繁的 ...
- HTTP 两种基本请求方法 GET和 POST的区别
GET方法 1.GET交互方式是从服务器上获取数据,而并非修改数据,所以GET交互方式是安全的.就像数据库查询一样,从数据库查询数据,并不会影响数据库的数据信息,对数据库来说,也就是安全的.2.GET ...