1. 设置软件断点,运行到目标位置启动调试器

方法①:使用汇编指令(注:x64 c++不支持嵌入汇编)

_asm int 

方法②:编译器提供的方法

__debugbreak();

方法③:使用windows API

DebugBreak();

WerFault.exe进程(Windows Error Reporting)弹出ConsoleTest.exe已停止工作:

要想出现“调试程序”选项,需要将Windows Error Reporting注册表信息设置成如下图所示(注:特别是红框的内容)

如果在注册表AeDebug的Debugger项配置了VSJitDebugger路径,且VSJitDebugger安装正常

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug

HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug  // 注:64位系统上的32位程序使用该注册表项

点击“调试程序”选项就会弹出Visual Studio实时调试器对话框,选择对应的调试器后,点击“是”就可以启动调试器并中断到软件断点位置了

需要注意的是,软件断点也是一种异常,一旦被处理,就不会传到WerFault.exe进程上,那么这种方法也就失效了!

下面两种情况软件断点异常会被处理:

① 被SEH异常捕获并处理

② 被自定义的全局异常函数处理

注:可以将上面两种情况中的EXCEPTION_EXECUTE_HANDLER修改为EXCEPTION_CONTINUE_SEARCH来指明异常未得到处理

2. 修改变量(注:在悬停出来小面板、Locals窗口、Autos窗口、Watch窗口、或Quick Watch窗口中进行修改;也可以在Immediate窗口中执行:bFlag=false)

3. 格式化变量

注:d,i:有符号的十进制数
      u:无符号的十进制数
      o:无符号的八进制数
      x:十六进制数(字母小写)
      X:十六进制数(字母大写)

更多详见:Format specifiers for C++ in the Visual Studio debugger

4. 修改内存(注:在内存窗口中,将光标定位到要修改的地方,直接按0-9输入十六进制;要输入a-f则需通过右键菜单中的“Edit Value”进行输入)

5. 格式化显示内存

6. 设置下一个运行位置(注:直接拖动黄色箭头到想要的运行位置)

示例中:传入的bFlag为true,代码开始运行到断点处(43行),然后重新把黄色箭头拖回39行,此时bFlag的值为false,按F10会进入else分支

注:(1)跳过中间所有指令。意味着:printf("True\n")及CTest的析构函数均不会被执行

(2)当拖动箭头到一个新的函数中时,vs会将原来的函数从栈中弹出,将新函数压入栈顶;

由于新函数与上层函数没有调用关系,输出类型的参数及返回值很有可能写坏上层函数的栈数据

(3)该调试技巧为一种事后行为,应谨慎使用,最好是只在函数内局部使用

7. 编辑然后继续运行

(1)不能在64位代码上使用

(2)使用“Program Database for Edit & Continue (/ZI)”生成pdb文件

(3)仅适用于函数内部改变(若要修改函数原型或增加新函数,只能选择重启程序)

8. 变量的一些特殊查看方法

以$和@开头的伪变量:(注:$和@两个符号是一样的,随便用哪个都可以)

$err -- 获取GetLastError()的返回值

$err,hr -- 获取GetLastError()的返回值并解释返回值的含义

@eax -- 查看eax的值(64位为@rax)

@esp+4 -- 函数的第一个参数地址

$handles -- 查看打开的句柄数

$pid -- 当前进程id

$tid  -- 当前线程id

$vframe  -- 当前栈帧的ebp

$clk  -- 以时钟周期为单位显示时间

$ReturnValue -- 查看函数的返回值

Message,wm --以windows消息的宏形式显示 如:Message为15时,显示为WM_PAINT(注:Message为unsigned int类型)

hResult,hr --hResult为0x80070005时,显示为E_ACCESSDENIED(注:hResult为void*类型)

pArray,10 --从pArray地址起显示后续10个int类型的数据(注:pArray为int*类型)

(pArray+5),3 --从pArray[5]地址起显示后续3个int类型的数据(注:pArray为int*类型)

更多详见:Pseudovariables in the Visual Studio debugger

9. 获取简单类型的函数返回值

注1:不能为inline函数

注2:执行函数的下一条语句时,查看eax或伪变量ReturnValue的值

10. 使用指针类型转换查看某个地址的变量

注:有时候,尽管对象仍然存在,在调试符号越界后,watch窗口中的变量是被禁用的,不能再查看(也不能更新)。

若知道对象的地址,则可以将地址转换为该对象类型的指针,放在watch窗中来继续观察它。

11. Command窗口

通过命令来完成vs中的功能(不仅仅在调试状态时使用),另外其调试相关命令与windbg保持一致。

? nLocal  //查看变量nLocal的值
?? nLocal //将nLocal添加到Quick Watch窗口中
? nLocal= //修改nLocal的值为100
? MySum(,) //调用全局函数MySum,并返回结果
k //打印当前线程堆栈
~ //查看线程情况
~*k //打印出所有线程的堆栈信息
watch //打开watch窗口
memory2 //打开memory2窗口
g //继续执行,F5功能
q //结束调试

12. 内存断点

(1)在84行断点停住后,查看&s.Age的地址为0x0042FCEC

(2)点击"Debug"-"New Breakpoint"-"New Data Breakpoint...",在弹出的对话框Address填入:0x0042FCEC,长度为4即可

(3)当运行到88行时,由于Scores数组越界引发了s.Age的内存修改,触发了内存断点

13. 条件断点

断点说明:

(1)设置断点条件:i>6;且被命中次数>=2时才断住程序,所以第一次断住时i=8

(2)命中时,在Output窗口中打印当前函数名及线程ID(也可以打印相关变量的值,详见"When Breakpoint Is Hit"面板上的说明);在Command窗口中打印出堆栈信息

(3)若不想断住程序,可以把"When Breakpoint Is Hit"对话框中的"Continue execution"勾选上

注1:对于字符串的条件断点,不能写如下条件pStr=="Hello"(pStr为char*类型),应该写成:pStr[0]=='H' && pStr[1]=='e' && pStr[2]=='l' && pStr[3]=='l' && pStr[4]=='o' && pStr[5]=='\0'

vs2010及以上版本中,条件断点中可使用字符串:strcmp(pStr, "Hello")==0

支持的字符串函数有:strlen, wcslen, strnlen, wcsnlen, strcmp, wcscmp, _stricmp, _wcsicmp, strncmp, wcsncmp, _strnicmp, _wcsnicmp, strchr, wcschr, strstr, wcsstr.

注2:也可以创建自己的宏,具体方法:"Tools"-"Macros"-"Macro Explorer",然后在下图:MyMacros-Module1上右键快捷菜单中选择"New macro",

如ChangeExpression宏函数会在Output窗口的Debugger过滤器下打印出"Hello World",然后修改变量code的值为1000

编写自己的宏时,可以参考大量vs已有的宏(见:Samples节点下)

Public Module Module1
Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True)
Dim window As Window
Dim outputWindow As OutputWindow
Dim outputWindowPane As OutputWindowPane window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
If show Then window.Visible = show
outputWindow = window.Object
Try
outputWindowPane = outputWindow.OutputWindowPanes.Item(Name)
Catch ex As Exception
outputWindowPane = outputWindow.OutputWindowPanes.Add(Name)
End Try
outputWindowPane.Activate()
Return outputWindowPane
End Function Sub ChangeExpression()
Dim bppane As EnvDTE.OutputWindowPane
bppane = GetOutputWindowPane("Debugger")
bppane.OutputString("Hello World")
DTE.Debugger.ExecuteStatement("code = 1000;")
End Sub
End Module

注3:如果弹出以下框,表明vs没有开启macro权限(Tools -- Options... -- Environment -- Add-in/Macro Security中勾选“Allow macros to run”)

注4:2014.2月windows系统更新后,各个版本的vs的宏失效。

详见:https://visualstudioextensions.vlasovstudio.com/2014/02/13/visual-studio-2010-macros-stop-working-after-february-2014-windows-update/

vs2005sp1补丁  vs2008sp1补丁   vs2010sp1补丁

14.在windows API上打断点

(1)例如:对SetWindowText打断点。首先当前程序字符集为未设置或多字节,则SetWindowTextA;为Unicode则为SetWindowTextW。下面以SetWindowTextA为例。

(2)调试运行程序断住后,打开Modules窗口可以看到所有已经加载的模块,找到windows API所在的模块,右击鼠标执行"Load Symbols From" - "Microsoft Symbol Servers"下载并加载对应模块的pdb

(3)新建一个Break At Function断点,填入:{,,user32.dll}_SetWindowTextA@8。可以看到,VS里面的符号跟windbg相比多了一些字符,其中‘_’表示stdcall类型,后面‘@8’表示所有参数的字节数的和。

有些函数Symbol Name与导出函数名可能不一致,例如GetDC(HWND),其Symbol Name为NtUserGetDC,最后断点应填入:{,,user32.dll}_NtUserGetDC@4

注:查找windows API符号名可以使用windbg的x命令或者使用pdb解析工具(symView

也可以直接使用地址对windows API打断点(这种方式不需要符号的支持):如对GetDC打断点,可以用Dependency查看其在user32.dll中导出函数地址(Entry Point列):0x000172CC

然后在Modules窗口中获得user32.dll模块起始地址0x75840000,最后对两个值相加后的绝对地址处直接设置断点:{,,user32.dll}0x758572CC

通过以上方法也可以给malloc函数(vs2008 debug其dll为msvcr90d.dll,release的dll为msvcr90.dll;在UE4 vs2017的dll为ucrtbase.dll)打上断点

15. 异常(First-chance)时断住程序

在调试程序时,Output窗口有时会出现“First-chance exception in xxx.exe...”这样的信息。
一般来说,这是由于程序中发生了异常,被调试器捕获而产生的输出。
在调试器中运行程序时,如果程序产生异常,调试器会首先获得通知(即First-chance exception)。
若程序没有捕获该异常,则在结束进程之前,操作系统会再次通知调试器(即Second-chance exception,Last-chance exception)。

(1)在"Debug"-"Exceptions...",弹出如下对话框:点击Add按钮,新增一个int类型的C++ Exceptions异常,并勾选Thrown

(2)当int、int*、int&的异常被catch到时,会断住程序进入调试状态(注:以上void类型对应:char*、void*的异常)

16. 单步调试自动跳过不必进入的函数  (注:仅适用于Native c++)

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\NativeDE\StepOver]
"1"="\\scope:CString.*\\:\\:.*=NoStepInto"

注1:如果是32位windows,删除上面路径中的Wow6432Node

注2:不进入任何CString的方法(前面的1表示优先级,该值越大优先级越高)

++++++++++++++++++++++++++++++

NoStepInto 不可进入匹配函数
StepInto   可进入匹配函数

特殊字符串:

\cid 代表一个C/C++标识符
\funct 代表一个C/C++函数名
\scope 代表一个函数的作用范围(命名空间+类名 如:ATL::CFoo::CBar::)
\anything 代表一个字符串
\oper 代表一个C/C++操作符

正则表达式:

\ 转义字符 如:要使用 “\” 本身, 则应该使用“\\”
\: 代表字符:
. 匹配任意字符
* 其左边的字符被匹配任意次(0次或多次)。如:be*匹配“b”,“be”或“bee”
.* 匹配0个或多个字符

更多例子:

例1:不进入重载操作符函数:
10 \scope:operator\oper:=NoStepInto
例2:除了CComBSTRs的非操作符函数,不进入任何ATL::开头的函数:
20 ATL\:\:CComBSTR::\funct:=StepInto
10 ATL\:\:.*=NoStepInto
例3:除了全局模版函数外,不进入任何模板函数:
20 \scope:\funct:=StepInto
10 .*[\<\>].NoStepInto

++++++++++++++++++++++++++++++

17. 使用OutputDebugString进行日志调试

(1)调试状态时,会将日志输出到Debug过滤器的Output窗口中

(2)非调试状态时,可采用DbgView.exe来捕捉程序日志

18. 使用autoexp.dat自定义调试时变量的显示格式

文件所在位置:Microsoft Visual Studio 9.0\Common7\Packages\Debugger\autoexp.dat

在autoexp.dat中的[Visualizer]域可以对各种类型变量的显示格式进行配置,来优化变量在调试时显示,提高效率。

注1:在vs中要让autoexp.dat生效需要去掉"Tools"-"Options..."对话框中,

"Debugging"-"General"-"Show raw structure of objects in variables windows"的勾选

注2:vs2012版本后,autoexp.dat被废弃,改用.natvis文件,该文件需要安装到"%USERPROFILE%\Documents\Visual Studio 2012\Visualizers"目录中

如UE4引擎源码中的%EngineDir%\Engine\Extras\VisualStudioDebugging\UE4.natvis

(1) STL之string、vector、map

①原始显示结果:

②配置了autoexp.dat的显示结果:

-->对应的配置内容如下:

;  std::string -- char
std::basic_string<char,*>{
preview ( #if(($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,s]) #else ( [$e._Bx._Ptr,s]))
stringview ( #if(($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,sb]) #else ( [$e._Bx._Ptr,sb]))
children
(
#if(($e._Myres) < ($e._BUF_SIZE))
(
#([actual members]: [$e,!] , #array( expr: $e._Bx._Buf[$i], size: $e._Mysize))
)
#else
(
#([actual members]: [$e,!], #array( expr: $e._Bx._Ptr[$i], size: $e._Mysize))
)
)
}
;------------------------------------------------------------------------------
; std::vector
;------------------------------------------------------------------------------
std::vector<*>{
children
(
#array
(
expr : ($e._Myfirst)[$i],
size : $e._Mylast-$e._Myfirst
)
)
preview
(
#(
"[", $e._Mylast - $e._Myfirst , "](",
#array
(
expr : ($e._Myfirst)[$i],
size : $e._Mylast-$e._Myfirst
),
")"
)
)
}
;------------------------------------------------------------------------------
; std::map
;------------------------------------------------------------------------------
std::map<*>{
children
(
#tree
(
head : $e._Myhead->_Parent,
skip : $e._Myhead,
size : $e._Mysize,
left : _Left,
right : _Right
) : $e._Myval
)
preview
(
#(
"[", $e._Mysize, "](",
#tree
(
head : $e._Myhead->_Parent,
skip : $e._Myhead,
size : $e._Mysize,
left : _Left,
right : _Right
) : $e._Myval,
")"
)
)
}

(2) 自定义类MyArray

①原始显示结果:

②配置了autoexp.dat的显示结果:

-->对应的配置内容如下:

MyArray{
preview
(
#(
"[size is ", $c.m_nSize, "] m_pData is (",
#array
(
expr: ($c.m_pData)[$i],
size: $c.m_nSize
),
")..."
)
)
stringview
(
#(
"Hello MyArray!!!"
)
)
children
(
#(
#array
(
expr: ($c.m_pData)[$i],
size: $c.m_nSize
)
)
)
}

注1:双引号中字符串不能含有冒号,如:"[size is "不能写成"size: "

注2:多个类型使用 | 进行连接。如:MyArray|ArrayEx

注3:preview、stringview及children。对于不需要的部分可以不用定义,且三个部分没有先后顺序之分。

注4:格式的定义的最外层用大括号{},其中的每个部分使用小括号()。

注5:格式定义出错时,运行VS会弹出提示窗口,对于格式配置错误的类型,在调试期间无法正常显示。

注6:最外层的左边的大括号{必须紧挨着最后一个类型名,否则无论后面的格式正确与否,都无法正常显示。

注7:符号;为行注释符。

注8:$c表示当前所定义数据结构的对象,#array表示用数组形式显示内容,$i表示数组中的每个元素的索引,$e表示数组中的每个元素的值

注9:array结构必须同时包含expr和size两个部分,缺少其中一个部分都将导致信息无法正确显示。

注10:可使用#switch、#if进行条件分支判断,要注意的是:#switch结构不能用于#array结构中,否则可能导致VS挂死。

Visual Studio高级调试技巧的更多相关文章

  1. Visual Studio的调试技巧

    Visual Studio的调试技巧 [原文地址] Debugging Tips with Visual Studio 2010 [原文发表日期] 2010/8/19 10:48 AM 这是我写的关于 ...

  2. Visual Studio 使用调试技巧

    Visual Studio 使用调试技巧 这篇文章来源于http://damieng.com/blog/2014/02/05/8-visual-studio-debugging-tips-debug- ...

  3. 【.Net】Visual Studio的调试技巧

    这是我写的关于VS2010和.Net4发布的博客系列的第26篇. 今天的博文包含了一些有用的能用于VS的调试技巧. 我的朋友Scott Cate(他写了很多很好的关于VS使用技巧和窍门的博客)最近向我 ...

  4. 提高你开发效率的十五个Visual Studio 2010使用技巧

    提高你开发效率的十五个Visual Studio 2010使用技巧 相信做开发的没有不重视效率的.开发C#,VB的都知道,我们很依赖VS,或者说,我们很感谢VS.能够对一个IDE产生依赖,说明这个ID ...

  5. Android Studio 实用调试技巧

    Android Studio 是个发工具,其自身带调式环境是很强大的,我们要摆脱只会使用Log打印日志的低效的方法,掌握高级调试技巧对每个Android开发者都是很必要的,废话少说,直入正题 调试方式 ...

  6. (转载) Android Studio你不知道的调试技巧

    Android Studio你不知道的调试技巧 标签: android studio 2015-12-29 16:05 2514人阅读 评论(0) 收藏 举报  分类: android(74)    ...

  7. [No0000AE]在 Visual Studio 中调试 XAML 设计时异常

    在 Visual Studio 中进行 WPF, UWP, Silverlight 开发时,经常会遇到 XAML 设计器由于遭遇异常而无法正常显示设计器视图的情况.很多时候由于最终生成的项目在运行时并 ...

  8. 在Chrome+Visual Studio中调试asp.net程序很慢的问题(Firefox也有类似问题)

    在Chrome+Visual Studio中调试asp.net程序很慢的问题(Firefox也有类似问题) 今天开始起在Chrome中调试,发现问题主要出在菜单栏(layout文件)中,google了 ...

  9. 总是弹出visual studio 实时调试器 三种解决办法

    最近服务器老是弹出visual studio 实时调试器很是郁闷呀.关还关不掉.怎么解决呢 ,现像如下图所示: 下面我们一起来分析一下这种情况的原因: 弹出应用程序: Visual Studio 实时 ...

随机推荐

  1. Collection集合的功能及总结

    Collection集合是集合顶层接口,不能实例化 功能 1.添加功能 boolean add(Object obj):添加一个元素 boolean addAll(Collection c):添加一个 ...

  2. MyBatis源码分析(4)—— Cache构建以及应用

    @(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...

  3. split分割大文件--包含通过awk按规则分割文件到对应子文件

    当对一个大文件进行传输或者分析的时候,一个可以参考的办法是先通过split对文件进行分割,再对每个子文件进行处理,如果需要合并再进行合并. split函数可以按文件大小或者行数来进行分割. -a :  ...

  4. js设置鼠标悬停改变背景色

    看了网上那么多的js鼠标悬停时事件,大多数的,说了那么多话,也没解决什么问题,现在直接贴上代码,以供参考 html: <div id="sign">this is te ...

  5. Google地图路线规划

    Google地图路线规划: 需求:给定的两点之间Google地图路径规划和详情. 代码实现: //map定义省略 var directionsDisplay = new google.maps.Dir ...

  6. 利用FileSystemWatcher实现磁盘文件监控

    马上放假了,好开森啊O(∩_∩)O哈哈~ ——————————————————————————————————————————————————————— 昨天逛园子,发现了一个FileSystemWa ...

  7. 信息安全比赛总结(21ic转帖)

    我们的题目是基于这个ZedBoard的__视频流的人脸识别识别的算法采用的是PCA,,但是在后期的调试和实验中发现,,PCA的效果很容易受到环境,比如光照强度,背景,摄像头像素等影响:如果后期的改进的 ...

  8. c++语言友元函数和成员函数对运算符重载

    #include<iostream> using namespace std; /******************************************/ /*use mem ...

  9. Swift3.0P1 语法指南——继承

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...

  10. dom解析和sax解析的区别及优缺点

    dom解析一开始就将文档所有内容装入内存,每个元素(标签)都作为一个element对象存储,形成对象树,缺点是对内存占用大,不能解析数据量很大的文档:优点是方便进行crud操作. sax解析,逐行解析 ...