【C++】Visual Studio调试C++代码的13个技巧
创始人
2024-04-03 18:49:24
0

 

目录

前言

正文

一、打断点

二、逐语句执行和跳出执行

三、逐过程执行

三、运行到光标处

四、多次执行代码

五、快速监视

六、监视窗口

八、内存查看

九、局部变量

十、调用堆栈

十一、assert的使用

十二、条件断点

十三、函数断点


前言

  • 本文使用的是Visual Studio 2022社区版,但在老版本上依然适用(例如2019版)。
  • 本文旨在简单介绍一些调试的小技巧,进阶的调试技巧以后再做总结。
  • 本文基于Windows平台

正文

一、打断点

启用调试,第一步需要打断点:

注意:启动调试后,程序会执行到第一个断点出暂停,这里的第一个断点指的不是位置上的第一个(即代码行最靠前的那一个),而是逻辑上的第一个。例如上图,第24行的断点是最先执行的那一个。

二、逐语句执行和跳出执行

逐语句执行也叫“单步执行”或“逐行执行”,如果调用了一个函数,那么会进入这个函数中,而不是跳过函数。 

注意:这里的“逐行”,不是物理意义上的每一行,而是逻辑上的一行代码。

例如,上面第24行,判断条件里调用了2个函数,那么,会首先进入add()函数,返回后再进入sub()函数。

        注意:C++编译器对条件判断有一个优化,对于24行,如果add()为false,那就不会继续执行sub()了,如果add()为true,才会继续进入sub()函数。

跳出执行的用处是,如果进入函数后,不再希望用单步执行走完函数体内剩余的代码,那么可以跳出执行,直接返回:

 

三、逐过程执行

特点:无论当前代码行有多少个函数调用,都不会进入到函数中,而是直接进入到下一行代码并暂停。

三、运行到光标处

在没启动调试的时候,直接在想要定位的代码行处右键,选择运行到光标处,那么就会自动设置一个一次性断点,开始调试:

 

 注意:一次性断点的优先级是低于其它断点的,如果调试之前在某个位置打了断点A,并且这个断点在一次性断点之前(逻辑上),那么启用调试后,会首先来到断点A处。

四、多次执行代码

如果有些地方没弄清楚,那么可以在不重新打开调试的情况下,多次执行某些代码。

例如:

断点打在10行,执行完10行后,来到11行,但如果我还想再执行一次第10行,那就是“多次执行代码”了,方法很简单,就是:用鼠标把那个黄色箭头拖到第10行:

连续执行2次第10行: 

 

 

五、快速监视

在调试过程中,如果想要快速查看某个对象的信息,那么快速监视就挺有用,同时,还可以修改这个对象的值。

方法是:选中某个变量,右键:

 

 

六、监视窗口

调试的时候,如果要查看的变量很多,就需要用监视窗口,同时,可以打开多个监视窗口:

注1:和快速监视一样,监视窗口也能修改变量的值。只不过对于string这类较为复杂的类型来说,修改就相对麻烦,不能一次性修改,而是找到每个字符对应的位置,再修改:

注2:也可以监视一些表达式(有些不行,例如构造、析构、类型转换、预处理器宏等):

 

八、内存查看

目前还没有从内存层面去找bug,所以就举个查看内存的例子。

首先,启用调试,然后打开内存窗口:

默认窗口没有什么内容,只有一些随机的值:

当需要查看某个变量的内存占用时,只需要把这个变量拖到内存窗口:

同理,把wa也拖上去,对比a和wa的内存占用情况,可以看到wa是宽字符,每个字符占2个字节:(最后有一个结束符,也需要占一个字符大小的内存空间)

 

 

九、局部变量

  • 用来查看当前作用域下的变量:

test()里的p:  

 

 test0()里的p:  

 

 

  •  变量太多时,可以筛选想要显示的变量:

 

 

 

十、调用堆栈

可以查看函数的调用情况,每一个函数调用叫做“帧”,也称为“栈帧”;

栈底的函数最先被调用,栈顶的函数最后被调用:

 

十一、assert的使用

首先看一个很熟悉的窗口:

 这个实际上就是通过assert产生的,如果出现,不要点“中止”,而是点“重试”,这样就能找到代码出错的地方:

注意:

  1. 要导入头文件 #include
  2.  不要在assert里使用函数调用、对变量赋值!

关于第2点,《C++ Primer》第216页讲到,如果源文件定义了NDEBUG宏,那么assert就会失效,从而assert里的函数调用和赋值等操作都会被忽略,导致后面的错误!下面举例:

如果没有定义NDEBUG宏,那么assert是生效的,因此add函数会把相加的结果赋值给c:

#include 
int add(int a, int b)
{return a + b;
}
void test()
{int a = 10, b = 10;int c = 0;assert((c = add(a, b)) == 20); // 调用函数并赋值cout << c; // 输出20
}

如果定义NDEBUG宏:

#define NDEBUG
#include 
int add(int a, int b)
{return a + b;
}
void test()
{int a = 10, b = 10;int c = 0;assert((c = add(a, b)) == 20); // 这条语句会被忽略cout << c; // 输出0
}

 

十二、条件断点

通过举例来讲解:假如有一个for循环,需要在到达某个条件的时候,调试才停下来,而不是从一开始就停下来,那么此时就可以用条件断点:

 

启动调试: 

 

 

十三、函数断点

当我们知道一个函数名,但不知道函数具体在哪里的时候;或者函数被重载的时候,希望在每次调用函数的时候能够暂停;此时需要用到函数断点:

 

启动调试,就会自动来到add函数的位置: 

 

 

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...