C语言:实用调试技巧(VS2024)_vs调试怎么看变量的值

在这里插入图片描述
在这里插入图片描述

拒绝-迷信式调试!!!!

调试是什么?

调试(英语:Debugging / Debug),调试是保证所提供的设备能够正常运行的必须程序。又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。

调试的基本步骤

  • 发现程序错误的存在
  • 以隔离、消除等方式对错误进行定位
  • 确定错误产生的原因
  • 提出纠正错误的解决办法
  • 对程序错误予以改正,重新测试

debug和release的介绍

Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。

Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。

对于下列代码debug和release的区别:

#include <stdio.h>
int main()
{
	int a = 10;
	printf("%d\n", a);
	return 0;
}

在上述代码所属的项目下分别产生debug和release的应用程序
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
从上图中两种不同版本的相同代码所产生的应用程序的大小却相差30kb。


而且两种版本的反汇编代码也有差异:
debug:
在这里插入图片描述
release:
在这里插入图片描述

release版本对于代码的优化,可用下列代码验证:

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = {0};
    for(i=0; i<=12; i++)
   {
        arr[i] = 0;
        printf("hehe\n");
   }
    return 0;
}

在这里插入图片描述
debug版本下代码,程序陷入死循环。


在这里插入图片描述
release版本下代码,程序正常运行。

原因:

变量在内存中开辟的顺序发生了变化,影响到了程序执行的结果。


注意:

在release环境下调试不易观察到变量的变化,所以平时程序员所编写代码的环境就是debug环境下的。

所以我们说调试就是在Debug版本的环境中,找代码中潜伏的问题的一个过程。

windows环境调试介绍

调试环境的准备
在环境中选择 debug 选项,才能使代码正常调试。
在这里插入图片描述

学会快捷键

在上方任务栏中调试窗口中:
在这里插入图片描述

最常使用的几个快捷键:
F10

逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", i);
	}
	return 0;
}

当我们按F10进入调试界面后,再继续按F10,程序就会从main函数开始一行一行的向下执行语句。
在这里插入图片描述
按F10可以从main函数的第一条语句依次执行到main函数结束。
但如果main函数中出现了其他函数调用,这时,你又想进入这个函数内部观察程序运行过程,这时你按F10会发现,箭头一下就跳过函数,进入下一条语句了,这是因为F10是逐过程执行的,一次执行跳过一行,无法进入函数内部观察。
这时你就需要使用F11进行调试了。

F11

逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的)。

#include <stdio.h>
void test()
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", i);
	}
}
int main()
{
	int a = 10;
	test();
	printf("%d ", a);
	return 0;
}

当我们按F10进入调试界面后,再继续按F10,程序运行到test函数时。
在这里插入图片描述

我们按一下F11。
在这里插入图片描述

箭头就会进入到test函数内部,再按F10就可以一行一行的执行代码了。


F5

启动调试,经常用来直接跳到下一个断点处。

F9

创建断点和取消断点
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。

F5与F9一般是配合来使用的。
示例:

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", i);
	}
	return 0;
}

当我们需要在程序执行到某条语句时停下来,就需要在那条语句前使用F9打断点,然后再按F5,程序就会执行到断点处停下来。

打断点操作:

先用鼠标选中要打断点的语句行,再按F9就打好断点了。再按一下F9就取消该行的断点了。
或者直接在该行打断点处用鼠标点一下,就打好断电了。再点一下也就取消该行的断点了。

打断点:
在这里插入图片描述
按F5:
在这里插入图片描述
程序执行到断点处停止。
接着再使用F10或F11继续调试即可。


注意:在调试时可以打多个断点,每按一次F5就会执行到下一个断点处。
在这里插入图片描述

当我们想进入循环体内部观察,假设我们要在 i == 5 的时候让程序停止下来,就可以在断点处设置一下停止条件。
在这里插入图片描述

我们用鼠标右键点击该断点,在此菜单中点击条件选项。
在这里插入图片描述
在条件设置框中输入断点条件即可。
在这里插入图片描述

在这里插入图片描述

此时按F5。
在这里插入图片描述
程序执行到断点处停止,此时 i == 5, 屏幕上打印了0,1,2,3,4。


CTRL + F5

开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。

这个快捷键就是正常的执行程序,不进行调试,CTRL + F5直接从main函数开头执行到结束,中间不停顿。

在这里插入图片描述


这里分享一篇博主的博客,它的文章中有非常详尽的快捷键介绍:

VS中常用的快捷键


调试的时候查看程序当前信息

查看临时变量的值

在调试开始之后,用于观察变量的值。
当我们按F10进入调试界面后,在上方任务栏中找到调试窗口,点开后有一个子菜单,再点来子菜单的窗口选项,就有各种查看变量的工具 :

  • 监视
  • 自动窗口
  • 局部变量
  • 调用堆栈
  • 内存
  • 反汇编
  • 寄存器

在这里插入图片描述

  1. 监视

在这里插入图片描述
在这里插入图片描述
在监视里可以添加你想观察的变量。内容可以包括(变量、表达式、地址)。
在这里插入图片描述
2. 自动窗口和局部变量

这两个工具的功能类似,都可以自动动态显示变量的变化值,由于他是自动显示的,有时无法一直观察某变量的变化。
在这里插入图片描述
这里就没法观察到a的值了。


总结

调试一般都是使用监视来观察变量的变化。

  1. 调用堆栈

在这里插入图片描述
在这里插入图片描述
压栈过程


在这里插入图片描述

在这里插入图片描述

出栈过程

通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置。


  1. 内存
    在这里插入图片描述
    在这里插入图片描述

在内存的搜索框中输入&arr然后回车就可以找到arr数组在内存中的空间地址的内容了。
在这里插入图片描述
这里一行代表了4个字节。(一个内存地址代表一个字节)
在这里插入图片描述
可以在这里调节一行显示几个字节的内容。

过内存,可以看到各个变量在内存中是如何变化的。


  1. 反汇编和寄存器
    反汇编代码中需要使用到寄存器。

寄存器寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。

进入调试界面,右击鼠标,有转到反汇编选项。
在这里插入图片描述
在这里插入图片描述
阅读这些代码需要用到反汇编知识。


调试代码的实例

实现代码:求 1!+2!+3!

这里一步一步来,先实现 n!的阶乘。
在这里插入图片描述
然后计算出各个数的阶乘后,相加即可。

#include <stdio.h>
int main()
{
	int n = 3;
	int i = 0;
	int ret = 1;
	int sum = 0;
	for (n = 1; n <= 3; n++)//从1到3
	{
		for (i = 1; i <= n; i++)//计算n!
		{
			ret \*= i;
		}
		sum += ret;//阶乘的和
	}
	printf("%d ", sum);
	return 0;
}

大家观察一下上述代码,有没有什么不妥的地方,我们来看看打印结果:
在这里插入图片描述
我们发现结果与正确结果不相同,明明我们求一个数阶乘的代码没有问题啊,可是错误在哪呢?这时就需要使用到调试来进行排错了。
调试
按F10进入调试界面,打开监视观察各个变量的值。
在这里插入图片描述
在未进入循环时各个值。


在这里插入图片描述

当第一层for循环完,ret 中为1的阶乘,值为1。


在这里插入图片描述
当第二层for循环完,ret 中为2的阶乘,值为2。


在这里插入图片描述
当第三层for循环完,ret 中为3的阶乘,值为12。
此时,ret中的值发生异常,说明程序出错在第三次for循环内部,当我们重新调试时,
在这里插入图片描述
从第二层for循环进入到第三层for循环时,发现ret 的初始值为2,为上一次循环遗留下的值,所以该程序问题在于每次计算一个数的阶乘时,需要把ret的值重新初始化为1。
修改:

#include <stdio.h>
int main()
{
	int n = 3;
	int i = 0;
	int sum = 0;
	for (n = 1; n <= 3; n++)//从1到3
	{
		int ret = 1;
		for (i = 1; i <= n; i++)//计算n!
		{
			ret \*= i;
		}
		sum += ret;//阶乘的和
	}
	printf("%d ", sum);
	return 0;
}

在这里插入图片描述
这就是一次完整的写代码及调试纠错的过程。在自己编写代码时可以参考步骤。


如何写出好(易于调试)的代码

优秀的代码

1. 代码运行正常
2. bug很少
3. 效率高
4. 可读性高
5. 可维护性高
6. 注释清晰
7. 文档齐全

常见的coding技巧:

  1. 使用assert
  2. 尽量使用const
  3. 养成良好的编码风格
  4. 添加必要的注释
  5. 避免编码的陷阱。

示范:

模拟实现库函数:strcpy

这里先了解一下strcpy 函数,在cplusplus.com网站上搜索一下这个函数。
在这里插入图片描述
从函数功能介绍来看,这个函数是将一个字符数组的内容复制给另一个字符数组,直到遇到’\0’后结束。第一个参数数组是被放入字符的数组,第二个参数数组是要复制的数组。
在这里插入图片描述

根据上述描述先实现一下核心功能,这里命名为my_strcpy函数。
在这里插入图片描述

这里可以用while循环把arr1的每一位复制到arr2数组中,最后再给arr2赋值一个’\0’。

#include <stdio.h>
void my\_strcpy(char\* dest, char\* src)
{
	while (\*src)
	{
		\*dest = \*src;
		dest++;
		src++;
	}
	\*dest = '\0';
}
int main()
{
	char arr1[] = "abcdefg";
	char arr2[10];
	my\_strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

在这里插入图片描述

思考:这样写就可以了吗?能否对代码进行再优化一下?
修改:

#include <stdio.h>
void my\_strcpy(char\* dest, char\* src)
{
	while (\*dest++ = \*src++)//这样是不是更简洁
	{
		;
	}
}
int main()
{
	char arr1[] = "abcdefg";
	char arr2[10];
	my\_strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/dbc0b6c31fc3258562b0e467cf90b0be.png)

 

![img](https://img-blog.csdnimg.cn/img_convert/2c38632efa9671dfa5fdfa2d55c8e7f7.png)

![img](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png)

![img](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)

![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)

![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**

几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中...(img-C4oYzjET-1712466139011)]

 

[外链图片转存中...(img-bTHixSgD-1712466139011)]

![img](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png)

![img](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)

![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)

![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**

<img src="https://img-community.csdnimg.cn/images/fd6ebf0d450a4dbea7428752dc7ffd34.jpg" alt="img" style="zoom:50%;" />
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在PyCharm中查看变量有多种方法。一种常用的方法是使用print函数输出变量。你可以在代码中使用print函数,并将需要查看的变量作为参数传递给它,然后运行代码,就可以在控制台中看到变量。另一种方法是使用PyCharm的调试功能。你可以在代码中设置断点,然后通过调试模式运行代码。当代码执行到断点时,你可以通过查看变量窗口来查看变量。你可以看到当前作用域内的所有变量,并且可以展开变量以查看其详细信息。如果在PyCharm的调试界面下方没有出现step等按钮及变量等内容,可能是由于某些设置问题。你可以参考一些解决方案来解决这个问题。总之,PyCharm提供了多种方法来方便快捷地查看变量,你可以根据自己的需求选择适合的方法来查看变量。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Python查看变量 / PyCharm调试](https://blog.csdn.net/NSJim/article/details/125942498)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [解决pycharm debug时界面下方不出现step等按钮及变量的问题](https://download.csdn.net/download/weixin_38747087/12851274)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值