前言

VS是非常强大的IDE,所以掌握VSVC的常用方法,将会使得我们找出问题解决问题事半功倍。

目录

VSVC的常用调试方法

前言

1. Watch窗口查看伪变量

2. 查看指针指向的一序列值

3. 内存泄露查找

4. 调试Release版本

5. 远程调试

6. 函数断点

7. 数据断点。

8. 代码执行时间

9. 格式化数据

10. 格式化内存

  1. 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. 查看指针指向的一序列值

例如有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,它是拥有数据的真实缓存。

  1. 内存泄露查找

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窗口里显示内存泄露的有关详细信息。

  1. 调试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

  1. 远程调试

如果能够用打印调试信息解决问题的,就尽量不要使用远程调试了。感觉远程调试,总是容易出各种问题。但有的时候还必须得使用远程调试,所以在此简单介绍下。

  • 将本地电脑上的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

  1. 函数断点

函数断点,我们经常用,鼠标移到某一行,按下F9,即设置了最普通的断点。断点还有很多高级功能,熟练掌握,能够让我们调试更方便。

  • 条件断点,条件只要是表达式即可。

  • 触发次数断点。

  • 过滤断点。

  1. 数据断点。

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

数据断点可以用来查找某个变量在复杂的代码里,究竟是在哪里产生的改变。另外,针对内存覆盖导致的崩溃,用数据断点也是比较方便。内存覆盖导致的崩溃,往往是某个重要变量被影响到了导致的。所以我只要找到重要变量,用数据断点监控起来就可以了。

  1. 代码执行时间

伪变量中有一个特别的@clk,默认显示系统时钟时间,以毫秒为单位。

在第一次断点时,将@clk放入Watch窗口,并将Value清0.

第二次断点时,@clk对应的Value即为两个断点之间代码的大概执行时间。

  1. 格式化数据

当你在Watch或Quick Watch窗口查看变量时,这值是用默认的预定义可视化显示的。当它变成数字时,它们是通过它们的类型(整形、浮点、双精度)用十进度制来显示的。但你能够强制让这调试器用不同类型或不同进制或是两者来显示这些数字。

给变量加前缀来改变显示 :

  • by 针对无符号字符(又称无符号字节)
  • wo 针对无符号短整形 (又称无符号字)
  • dw 针对无符号长整形(又称无符号双字)

给变量名加后缀来改变显示:

  • , d 或者 , i 针对有符号十进制
  • , u 针对无符号十进制
  • , o 针对无符号八进制
  • , x 针对小写的十六进制或 , X 针对大写的十六进制

  1. 格式化内存

除了格式化数据,调试器也能在Watch窗口中显示格式化的内存值,高达64个字节。你能用下面的说明符在表达式(变量或内存地址)后来格式化数据。

  • mb / m - BYTE
  • mw - WORD
  • md - DWORD
  • mq – 8BYTE
  • ma – 16BYTE
  • mu – 2BYTE UNICODE characters

  1. 其他

一段代码进入死循环,如何快速找到在哪里呢?直接点击中断所有。

应用程序打开异常,调用DLL异常,使用dependens.exe。

VC的常用调试方法的更多相关文章

  1. shell 脚本常用调试方法

    曾经我刚开始学习 shell 脚本时,除了知道用 echo 输出一些信息外,并不知道其他方法,仅仅依赖 echo 来查找错误,比较难调试且过程繁琐.效率低下.本文介绍下我常用的一些 shell 脚本调 ...

  2. iPhone页面的常用调试方法

    在iPhone中调试,大体上与上文 安卓中的移动页面调试 类似,区别主要是iOS系统中的一些限制,导致某些工具无法使用. 本文基于此,简要介绍在iPhone中如何调试页面. 最终可以实现在Mac平台使 ...

  3. 【转】 GDB 常用调试方法

    一.多线程调试 多线程调试可能是问得最多的.其实,重要就是下面几个命令: info thread 查看当前进程的线程. thread <ID> 切换调试的线程为指定ID的线程. break ...

  4. onvif规范的实现:onvif开发常用调试方法 和常见的segmentation fault错误

    在前几篇中,虽然已经实现了rtsp视频流的对接,但是还要做的工作还非常多,onvif本来就是一个覆盖面非常广的一个协议,每一个功能都要填充大量的函数.而且稍不注意就会出现segmentation fa ...

  5. Makefile常用调试方法

    转载自 陈皓<跟我一起写 Makefile><GNU Make项目管理> GNU make 提供了若干可以协助调试的内置函数以及命令行选项. 1.warning函数 $(war ...

  6. shell常用调试方法

    检查语法 -n选项只做语法检查,而不执行脚本. sh -n script_name.sh 启动调试 sh -x script_name.s 进入调试模式后,Shell依次执行读入的语句,产生的输出中有 ...

  7. sqlprofiler 常用调试方法

  8. VC调试方法大全

    VC调试方法大全 一.调试基础 调试快捷键 F5:  开始调试 Shift+F5: 停止调试 F10:   调试到下一句,这里是单步跟踪 F11:   调试到下一句,跟进函数内部 Shift+F11: ...

  9. eclipse 常用快捷键及调试方法

    原文链接:http://my.oschina.net/u/1054538/blog/741561 常用快捷键 Eclipse最全快捷键,熟悉快捷键可以帮助开发事半功倍,节省更多的时间来用于做有意义的事 ...

随机推荐

  1. SSM 框架基于ORACLE集成TKMYBATIS 和GENERATOR自动生成代码(Github源码)

    基于前一个博客搭建的SSM框架 https://www.cnblogs.com/jiangyuqin/p/9870641.html 源码:https://github.com/JHeaven/ssm- ...

  2. 20155211 2016-2017-2 《Java程序设计》第十周学习总结

    20155211 2016-2017-2 <Java程序设计>第十周学习总结 教材学习内容总结 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输 在实际传输数据以前需要将域 ...

  3. 20155222 卢梓杰 myod

    20155222 卢梓杰 myod 复习c文件处理内容 编写myod.c 用myod XXX实现Linux下od -tx -tc XXX的功能 main与其他分开,制作静态库和动态库 编写Makefi ...

  4. 20155317王新玮 2016-2017-2《Java程序设计》第2周学习总结

    20155317 2016-2017-2<Java程序设计>第2周学习总结 课本知识: 认识类型与环境 整数:包括short,int,long .它们分别占用2个字节,4个字节和8个字节. ...

  5. C语言学习笔记1

    C语言假期学习笔记1 关于吃回车问题 第一个解决方案是使用ch=getchar(); 第二个方案是在scanf(" %c",&b):在%c加空格,将存于缓冲区的回车符读入 ...

  6. nohub用法

    在应用Unix/Linux时,我们一般想让某个程序在后台运行,于是我们将常会用 & 在程序结尾来让程序自动运行.比如我们要运行mysql在后台: /usr/local/mysql/bin/my ...

  7. plsql高级查询命令

    一.DDL数据定义语言:表操作 1.新建表 SQL> create table good(id number,name varchar2(10)); 添加注释 SQL> comment o ...

  8. 1109: [POI2007]堆积木Klo

    1109: [POI2007]堆积木Klo https://lydsy.com/JudgeOnline/problem.php?id=1109 分析: 首先是dp,f[i]表示到第i个的最优值,f[i ...

  9. SaltStack入门篇(一)之SaltStack部署

    一.SaltStack概述 Salt,,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯. salt底层采用动态的连接总线, ...

  10. 在sql server 中查找一定时间段内访问数据库情况

    total_worker_time AS [总消耗CPU 时间(ms)], execution_count [运行次数], qs.total_worker_time AS [平均消耗CPU 时间(ms ...