.在debug->windows下,有以下调试窗口
1)Breakpoints管理断点信息
可以新建条件断点,函数断点,以及特定地址改变断点(用于检测数据发生改变时机点)
在断点处,可以进入汇编语言查看汇编信息
断点详细信息包括: condition, hit count, funcion, file, address, process 等详细信息
2)Memory 给出了内存地址上详细信息,可查看各种变量,结构体,类等内存状态
3)Registers 给出了寄存器相关信息,在调试汇编时可以查看寄存器信息
4)Processes 给出进程相关信息,包括 ID, path等
5)Moudules 给出了调用模块列表,一般控制台程序会调用如下模块:
ucrtbased.dll
vcruntime140d.dll
KernelBase.dll
kernel32.dll
ntdll.dll windows内核提供的所有原生API基本都是从该库中导出
6)Threads 给出了当前进程的所有线程信息,一个空的控制台程序包括一个主线程及多个工作线程,
其中,三个工作线程均来自于 ntdll.dll,在 Location 处,通过展开调用栈可以查看线程具体信息
7)CallStack 给出了程序调用栈信息,根据调用栈可以进行调用回溯
8)Watch 可查看变量值,也可以修改变量值继续调试,变量值可以用10进制或者16进制显示
.程序调试过程中,可以拖动调试点重新执行已经执行过代码,方便问题查找与确认
.#include <assert.h> assert() function可以检测一些断言错误,调试assert方法如下:
1)使所有断点无效
2)debug 程序,程序会提示断言错误,点击重试即可定位错误
3)如果不调试而直接运行程序,断言错误仍旧会被抛出,但是无法进入代码查看更加具体信息
.编辑并继续执行
1)设置 c/c++->General->Debug Information Format = Program Database for Edit And Continue
2)设置 Linker->optimaization->References = No(/OPT:NOREF)
3)将断点拖拽至待继续执行代码前
4)修改待继续执行代码,继续调试即可应用编辑后代码
.GetLastError() 返回上次执行函数的返回值,在 Tools->Error lookUp 下可查看错误对应的具体信息
同时,在监视窗口中输入 err 或 err,hr 可查看上次返回值情况
.在监视窗口(watch)中,可以使用 sizeof 运算符计算结构体,数组等大小信息
.x86架构为小端存储,对于unicode编码,如 t=0x0074, 在内存地址中则存储为 74 00,其实小端存储更加符合计数规则
.相同成员变量的类与结构体在内存空间表示是一致的,调整成员变量顺序可以优化内存占用,规则如下:
将变量按占用空间从小到大排列,可以最大化优化内存占用(基于结构体对其原则)
.内存泄漏调试
1)引入以下语句
#define _CRTDBG_MAP_ALLOC // 必须在包含crtdbg.h前预定义该宏,使得malloc函数重定义
#include <crtdbg.h> // 用于c运行时库的调试,不包含 new 运算符重定义
#ifdef _DEBUG
#define new new(_CLIENT_BLOCK, __FILE__, __LINE__) // 重定义 new 运算符
#endif
2)在程序入口点设置内存泄漏检测
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF);
3)在程序结束处输出内存泄漏
_CrtDumpMemoryLeaks();
4)注意,仅在调试模式下可以定位泄漏,关闭程序后 output 窗口大致给出如下信息
Detected memory leaks!
Dumping objects ->
d:\debug\practice\practice\practice.cpp(19) : {87} normal block at 0x013B78D8, 100 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
d:\debug\practice\practice\practice.cpp(18) : {86} client block at 0x015B5040, subtype 0, 1048576 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
双击提示信息,即可进入内存泄漏点
5)根据 4)给出的提示信息,在第 86,87 次分配中存在内存泄漏,在程序开始处添加 _CrtSetBreakAlloc(86),
再次调试运行程序,程序将会在第 86 次分配内存前停下,内存泄漏位置定位成功
.定位堆内存破坏(调试模式下)
1)在调试模式下,堆内存分配会在分配内存空间后边增加一些调试信息,
如 char *p= new char[2] 在内存中表示为 cd cd fd fd fd fd ...,
当delete []p 调用时,程序会检测 fd fd fd fd 是否发生改变,如果发生改变则提示堆内存错误。
2)在 Release 模式下, 程序不会添加附加信息,因此不会检测堆内存被破坏错误,
但是在 Release 模式下,由于没有 fd fd fd fd ... 形式的缓冲区,程序越界改写数据可能导致一些奇特的且不固定的错误!!!
3)在调试模式下,检测堆内存破坏可使用数据断点(Data Breakpoint),这里可以设置 p + 5 数据发生改变后触发断点,
然后在调用堆栈中即可定位错误,注意,数据断点设置需要获得数据所在的准确内存地址(即数据指针有效后方可设置该数据相关的数据断点)
.定位堆内存破坏(Release模式下)
1)在 Release 模式下,使用 devenv.exe 启动调试,当操作系统为程序分配堆内存时,在其后邻接位置分配保护内存,利用检测保护内存触发越界。
2)在注册表 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options 下增加调试应用程序 x.exe。
3)增加如下选项 Debugger(REG_SZ)=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe
GlobalFlag(REG_SZ)=0x02000000 PageHeapFlags(REG_SZ)=0x2
4) 点击 x.exe 启动调试器,当前调试器好像只能在堆内存释放时定位问题,与预期不太一致?代码如下:
char *p = new char[5]; memcpy(p, "123456", 6); delete[]p;
5)要定位到源码,需要保证 .pch 及源码文件路径未发生改变
.栈破坏可以使用数据断点进行监测, 设置数据断点,当触发了预期以外的断点,则表示该栈数据被破坏,
同样,该方法也适用其他任何数据破坏的监测。

vc++调试总结的更多相关文章

  1. VC++调试说明

    目录 第1章调试说明    1 1.1 调试设置    1 1.2 跟踪代码    2 1.3 断点    2 第2章模块生命周期    4 2.1 exe模块    4 2.2 dll模块    5 ...

  2. VC调试篇

    难怪很多前辈说调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言.不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件. 我以前接触的程序大多是有比较成形的思路和方法,调试起来出 ...

  3. VC++调试基础

    一.调试基础 调试快捷键 F5:  开始调试 Shift+F5: 停止调试 F10:   调试到下一句,这里是单步跟踪 F11:   调试到下一句,跟进函数内部 Shift+F11:  从当前函数中跳 ...

  4. gdb对应vc调试命令

    gdb vc调试对照表: 实现功能                vc                   gdb 修改后编译              f7                   ma ...

  5. VC调试篇:ASSERT(FALSE)时怎么办?查看调用堆栈

    问题简述 我们在调试程序时,经常会遇到程序中断的情况,就像下图这样. 我艹,这该怎么办,我们一下子就懵逼了.我们选择中断,常常会跳到一个莫名其妙的地方去. 正是这个断言 ASSERT(::IsWind ...

  6. vc调试大全

    一.调试基础 调试快捷键 F5:  开始调试 Shift+F5: 停止调试 F10:   调试到下一句,这里是单步跟踪 F11:   调试到下一句,跟进函数内部 Shift+F11:  从当前函数中跳 ...

  7. VC调试方法大全

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

  8. VC调试笔记

    1.windows-32调试: ①使用map文件根据崩溃地址寻找对应的源代码文件和行号 勾选project->settings->link->General mapfile,对应的P ...

  9. VC++调试错误的解决方案

    这篇文章主要用来记录使用Visual Studio过程中,出现的各种error,并提供自己当时解决的方案.但是,一个error可能由不用原因引起的,文中案例仅供大家参考. nafxcwd.lib(th ...

  10. VC 调试版(Debug Version)和发行版(Release Version)

    调试是纠正或修改代码,使之可以顺利地编译.运行的过程.为此,VC IDE提供了功能强大的调试和跟踪工具. 1.1.1 调试版(Debug Version)和发行版(Release Version) 开 ...

随机推荐

  1. a href 鼠标滑过变成小手图标

    <a id="l05" style="cursor:pointer;text-decoration:none;" href="<%=pat ...

  2. Linux上天之路(十六)之Shell编程一

    用户在命令行输入命令后,一般情况下Shell会fork并exec该命令,但是Shell的内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程.以前学过的cd.alias.u ...

  3. 自定义异步爬虫架构 - AsyncSpider

    作者:张亚飞 山西医科大学在读研究生 1. 并发编程 Python中实现并发编程的三种方案:多线程.多进程和异步I/O.并发编程的好处在于可以提升程序的执行效率以及改善用户体验:坏处在于并发的程序不容 ...

  4. GoLang设计模式19 - 桥接模式

    桥接模式是一种结构型设计模式,通过桥接模式可以将抽象部分和它的实现部分分离.这看着有点儿奇怪,接下来会作详细说明. 桥接模式建议将一个较大的类拆分成两中角色. 抽象角色 - 抽象角色是一个接口.它的子 ...

  5. Sentry 企业级数据安全解决方案 - Relay 操作指南

    内容整理自官方文档 本篇回顾了我们在自托管外部使用 Relay 时的操作指南,即在您的硬件上运行的 Relay 并将事件转发到 sentry.io. 系列 Sentry 企业级数据安全解决方案 - R ...

  6. VUE3 之 全局组件与局部组件

    1. 概述 老话说的好:忍耐是一种策略,同时也是一种性格磨炼. 言归正传,今天我们来聊聊 VUE 的全局组件与局部组件. 2. 全局组件 2.1 不使用组件的写法  <body> < ...

  7. 校招面试之——Java容器

    最近校招季,特把自己面试中遇到的问题整理整理,以巩固自己的知识. Java中对于容器有两大类存储方式,一种是单元素存放,还有一种就是key-value这种有关联的双元素存放了.对于Java中的容器,有 ...

  8. Chrome插件:提醒你正在摸鱼,摸鱼的时候知道自己在摸鱼,减少摸鱼的时间和频率。

    stop-mess-around 项目介绍 减少摸鱼的时间和频率的Chrome插件:在上班/学习期间很容易下意识的打开摸鱼网站,插件帮助我们减少摸鱼的时间和频率,提高我们上班和学习的效率,节省时间用于 ...

  9. 解决windows下因为防火墙无法通过go get 下载gin的问题

    使用: go get -u github.com/gin-gonic/gin 出现以下错误: unrecognized import path "gopkg.in/yaml.v2" ...

  10. golang中通过递归或通道实现斐波那契数列

    1. 循环实现 package main import "fmt" func fibonacciFor(nums int) (s1 []int) { // 循环实现斐波那切数列 n ...