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最全快捷键,熟悉快捷键可以帮助开发事半功倍,节省更多的时间来用于做有意义的事 ...
随机推荐
- Linux内核程序的编译:模块化编译
内核在编译的时候,可以支持单独模块化编译,只需要一个小小的Makefile即可搞定. 步骤如下: 1.在任意位置创建目录 vim Makefile 2.在Makefile中添加如下代码(我的kerne ...
- 08-可滚动Widget
可滚动Widget ViewPort视口 在Flutter中,术语ViewPort(视口),如无特别说明,则是指一个Widget的实际显示区域.例如,一个ListView的显示区域高度是800像素,虽 ...
- Eclipse怎么恢复默认界面
Eclipse里面将界面恢复到默认状态: 1.选择Eclipse的工具栏里面的“窗口(Window)”,找到“复位透视图(Reset Perspective)”选项: 2.单击“复位透视图(Reset ...
- java入门---循环结构 - for, while 及 do...while&break&continue
顺序结构的程序语句只能被执行一次.如果您想要同样的操作执行多次,,就需要使用循环结构.Java中有三种主要的循环结构: while 循环 do…while 循环 for 循环 在Jav ...
- C语言字节对齐问题详解(对齐、字节序、网络序等)
首先说明一下,本文是转载自: http://www.cnblogs.com/clover-toeic/p/3853132.html 博客园用的少,不知道怎么发布转载文章,只能暂时这样了. 引言 考虑下 ...
- 20155218 《Java程序设计》实验五(网络编程与安全)实验报告
20155218 <Java程序设计>实验五(网络编程与安全)实验报告 一.实验内容及步骤 (一) 编写MyBC.java实现中缀表达式转后缀表达式的功能 编写MyDC.java实现从上面 ...
- [agc006D]Median Pyramid Hard-[二分+乱搞]
Description 题目大意:给你一个长度为n*2-1的排列,将除了该序列头尾的两个数外的其他数(设为i)变为原序列i-1,i,i+1下标数的中位数.求最后的数是什么.例子如下: Solution ...
- Hibernate三种状态的区分,以及save,update,saveOrUpdate,merge等的使用
Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object ...
- DB知识点记录
DB知识点记录 分页 SqlServer:ROW_NUMBER () over (ORDER BY ID) AS RN, MySql:limit Oracle:ROWNUM AS RN 数据表的基本结 ...
- 使用Python的Requests库进行web接口测试
1.Requests简介Requests 是使用 Apache2 Licensed 许可证的 HTTP 库.用 Python 编写,真正的为人类着想. Python 标准库中的 urllib2 模块提 ...