Visual Studio的实用调试技巧总结

        对于很多学习编程的老铁们来说,是不是也像下面这张图一样写代码呢?

        那当我们这样编写代码的时候遇到了问题?大家又是怎么排查问题的呢?是不是也像下面这张图一样,毫无目的的一遍遍尝试呢?

        这篇文章我就以 Visual Studio 2022编译器为例,带大家了解在Visual Studio2022编译器上是 如何进行调试C语言代码的。

1. 调试是什么?有多重要

1.1 调试的概念

        调试是什么:调试(英文:Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。

1.2 调试的基本步骤

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

1.3 Debug和Release的介绍

        Debug: 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
        Release: 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。(该版本不方便程序员调试)。

1.4 Debug和Release版本的对比

        因此,我们平常在编译器中写代码时,都是用的Debug版本。并且我们说调试就是在Debug版本的环境中,找代码中潜伏的问题的一个过程。

        对于如下同一份代码,我们来看看在 Debug环境 和 Release环境 中的结果展示:

#include<stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6 };
	int* p = arr;

	printf("%d\n", *(p + 2));

	return 0;
}

        Debug环境中:

        Release环境中:

        由结果中可以看出,Release环境下的执行文件(即 .exe文件)会比 Debug环境下的执行文件小好几倍,这是因为Release版本会对代码进行各种优化,因此这种版本也并不适合我们进行调试。

        那编译器进行了哪些优化呢?再来看看下面这段代码在两种环境下的结果展示:

#include<stdio.h>

int main()
{
	int i = 0;
	int arr[10] = { 0 };

	for (i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("hahaha\n");
	}
	return 0;
}

        同样的代码,在Debug环境中死循环,在Release环境下却能正常运行。这时我们通过调试看看这段代码在两种环境下的反汇编展示对比:

        观察两种环境下的汇编指令可以看出,Release版本会删除一些不必要的指令,从而使得编译器在运行代码时速度上是最优的。

        这时候也许有老铁会疑惑为什么这段代码在Debug环境下死循环报错(依赖于编译器的环境,在x86环境下会死循环,x64环境下会报错)呢?下面我就给大家仔细讲讲。

        首先要知道的是,局部变量在内存中的栈区上开辟空间的,而栈区内存空间的使用习惯:先使用高地址处的空间,再使用低地址的空间 (在不同的编译器上有所区别),如下图所示

        而数组,随着下标的增长,地址是由低到高变化的,且数组内存是连续存储的。因此上述代码中通过for循环对数组进行越界访问,并对数组元素重新赋值为0,这样就可能会导致arr[10] —— arr[12]中所开辟的内存空间 与 局部变量i 所开辟的内存空间重叠,从而导致 变量i 的值被修改为0,进而陷入死循环。

        这也提醒我们在对数组进行访问时千万不能越界访问呀!!

2. Windows环境调试介绍

        在对代码进行调试前,一定要将编译器的环境设置为 Debug版本,这样才能正常调试!

2.1 Visual Studio中常用的一些快捷键

        F5 —— 启动调试,经常用来直接跳到下一个断点处(切换断点)
        F9 —— 创建断点和取消断点。断点的重要作用,可以在程序的任意位置设置断点。这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。
        F10 —— 逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。(逐过程简单的说,就是当遇到函数调用时,直接就执行完成了,而不会进入到函数内部。)
        F11 —— 逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的)。(逐语句简单点说,就是当遇到调用函数时,会进入函数内部逐一执行每条语句。)
        CTRL + F5 —— 开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。

如果直接按 F5 没用,就试试 Fn+F5,其他快捷键也是一样的。如果忘记这些快捷键了,Visual Studio上也有提示的。

        当进行调试后,就能看到以下窗口,记住一定要调试启动后才能看到

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

        对于一份优秀的代码,通常会有以下几个特性:

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

4. 常见的coding技巧

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

这里给大家讲解一下第一点assert。

        assert是一个库函数(调用是需要包含头文件:#include<assert.h>),又为 断言 —— 只要不符合assert内的判断则会报错,反之则代码正常运行。

        举例如下:

        当我们用 assert 来判断所传的地址是否为空地址时,如果不为空,则代码正常运行,反之则报错(Assertion failed: p != NULL),这样通过assert函数就能很好的指出代码的问题。

5. 常见的编译错误

        1. 编译型错误:直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。(一般找到的都是语法问题)
        2. 链接型错误:看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不存在或者拼写错误。
        3. 运行时错误:借助调试,逐步定位问题。最难搞。

 

        最后就是如果我们想要在将来写出一份优秀的代码,一定要熟练掌握调试技巧,并且多使用快捷键,提升效率。只有多动手,尝试调试,我们才能有进步!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/889760.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iPhone使用指南:如何在没有备份的情况下从 iPhone 恢复已删除的照片

本指南将向您展示如何在没有备份的情况下从 iPhone 恢复已删除的照片。我们所有人在生活中的某个时刻都一定做过一些愚蠢的事情&#xff0c;例如从手机或电脑中删除一些重要的东西。这是很自然的&#xff0c;没有什么可羞耻的。您可能在辛苦工作一天后回来。当突然想看一些照片…

科技云报到:云服务的中场战事,从AI应用开始

科技云报到原创。 从去年的大模型之战&#xff0c;到今年的AI应用之争&#xff0c;云服务正在迈入全新的发展阶段。AI这个杠杆将各家厂商的竞争策略更向前推进了一步。 “云AI”能够孵化出多少可能&#xff1f;在业界眼中&#xff0c;“云AI”则意味着新的悬念&#xff1a;云计…

Java基础知识全面总结

第一章&#xff1a;类与对象 第一课&#xff1a;什么是面向对象编程 1.面向对象编程和面向过程编程的区别 无论是面向过程编程还是面向对象编程都是用于解决一个实际问题&#xff0c;当面向过程编程在解决一个问题时&#xff0c;更多的情况下是不会做出重用的设计思考的&…

蓝桥杯【物联网】零基础到国奖之路:十七. 扩展模块之单路ADC和NE555

蓝桥杯【物联网】零基础到国奖之路:十七. 扩展模块之单路ADC和NE555 第一节 硬件解读第二节 CubeMx配置第三节 代码1&#xff0c;脉冲部分代码2&#xff0c;ADC部分代码![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/57531a4ee76d46daa227ae0a52993191.png) 第一节 …

pytorh学习笔记——波士顿房价预测

机器学习的“hello world”&#xff1a;波士顿房价预测 波士顿房价预测的背景不用提了&#xff0c;简单了解一下数据集的结构。 波士顿房价的数据集&#xff0c;共有506组数据&#xff0c;每组数据共14项&#xff0c;前13项是影响房价的各种因素&#xff0c;比如&…

Nullinux:一款针对Linux操作系统的安全检测工具

关于Nullinux Nullinux是一款针对Linux操作系统的安全检测工具&#xff0c;广大研究人员可以利用该工具针对Linux目标设备执行网络侦查和安全检测。 该工具可以通过SMB枚举目标设备的安全状况信息&#xff0c;其中包括操作系统信息、域信息、共享信息、目录信息和用户信息。如…

第四次论文问题知识点及问题

1、NP-hard问题 NP-hard&#xff0c;指所有NP问题都能在多项式时间复杂度内归约到的问题。 2、启发式算法 ‌‌启发式算法&#xff08;heuristic algorithm&#xff09;是相对于最优化算法提出的。它是一种基于直观或经验构造的算法&#xff0c;旨在以可接受的花费给出待解决…

『网络游戏』进入游戏主城UI跳转主城【26】

首先在Unity客户端中创建一个空节点重命名为MainCityWnd 设置父物体为全局 创建空节点钉在左上角作为角色信息UI 在钉子下创建Image 创建脚本&#xff1a;MainCityWnd.cs 编写脚本&#xff1a;MainCityWnd.cs 挂载脚本 创建脚本&#xff1a;MainCitySys.cs 编写脚本&#xff1a…

Java中二维数组-杨辉三角

使用二维数组打印一个10行杨辉三角 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1&#xff09;第一行有1个元素&#xff0c;第n行有n个元素 2&#xff09;每一行的第一个元素和最后一个元素都是1 3&#xff09;从第三行开始&#xff0c;对于非第一个元素和最后一个元素的元素…

商贸物流痛点解析

商贸物流痛点解析 在当今全球化的商业环境中&#xff0c;商贸与物流之间的紧密协作已成为业务成功的关键因素。然而&#xff0c;许多组织面临着信息不对称、资源配套不足以及系统间隔离等痛点&#xff0c;这些问题严重阻碍了商贸体系与物流、仓储和园区的有效联动&#xff0c;…

[mysql]多表查询详解

我们如果要查询,我们就要用 SELECT .... FROM .... WHERE AND/OR/NOT #我们需要用过滤的条件来对数据进行筛选,不然会有很多多余数据 ORDER BY (ASC/DESC)#排序 LIMIT....,#是在几个有限的数据库管理系统里所以,PGsql,mysql,等 多表查询的意义 我们目前为止的查询语句…

linux 安装gitlab

安装环境 CentOS 7.7 (centos6.10会报错)2g内存防火墙关闭 安装步骤&#xff1a; 1 安装gitlab # yum install -y git curl policycoreutils-python openssh-server # 安装依赖 # wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-10.2.2-ce…

IPv 4

IP协议 网络层主要由IP&#xff08;网际协议&#xff09;和ICMP&#xff08;控制报文协议&#xff09;构成&#xff0c;对应OSI中的网络层&#xff0c;网络层以实现逻辑层面点对点通信为目的。目前应用最广泛的IP协议为IPv4 基本概念给出 主机&#xff1a;配有IP地址但不具有路…

【原创】java+springboot+mysql劳动教育网系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

【数据结构-栈】【贪心】力扣2434. 使用机器人打印字典序最小的字符串

给你一个字符串 s 和一个机器人&#xff0c;机器人当前有一个空字符串 t 。执行以下操作之一&#xff0c;直到 s 和 t 都变成空字符串&#xff1a; 删除字符串 s 的 第一个 字符&#xff0c;并将该字符给机器人。机器人把这个字符添加到 t 的尾部。 删除字符串 t 的 最后一个 …

让AI像人一样思考和使用工具,reAct机制详解

reAct机制详解 reAct是什么reAct的关键要素reAct的思维过程reAct的代码实现查看效果引入依赖&#xff0c;定义模型定义相关工具集合工具创建代理启动测试完整代码 思考 reAct是什么 reAct的核心思想是将**推理&#xff08;Reasoning&#xff09;和行动&#xff08;Acting&…

SDH8303直插DIP8,7W-12W非隔离升压降压转换器

SDH8303是用于开关电源的内置高压 MOSFET 的电流模式 PWM 控制器&#xff0c;采用DIP-8封装&#xff0c;全电压下典型功率7W-12W。 SDH8303芯片内置高压启动电路&#xff0c;在轻载下会进入打嗝模式&#xff0c;具有降频、抖频、软启动、VDD 打嗝功能&#xff0c;还集成了 VDD …

猿人学 — 第1届第17题(解题思路附源码)

猿人学 — 第1届第17题 根据题目“天杀的Http2.0”大概知道&#xff0c;请求的协议应该遵照的是Http2.0协议&#xff0c;并且目标网站专门对此进行了检测&#xff0c;在Network面板中右键表头&#xff0c;勾选Protocol 果不其然&#xff0c;一堆请求都是遵照Http2.0协议。而u…

论文阅读 BLIP-2

Bootstrapping Language-Image Pre-training with Frozen Image Encoders and Large Language Models 使用冻结的图像编码器和大型语言模型进行语言-图像预训练的引导 BLIP-2 通过一个轻量级的查询变换器弥合了模态之间的差距。 Querying Transformer 第一阶段通过冻结的图像编…

Word排版 | 如何文字部分固定行距、图片(嵌入型)单倍行距

问题描述 在写一个要求比较高的项目报告&#xff0c;总共有109页 89张图片&#xff0c;而且必须用word写 因此&#xff1a; 文字部分需要固定行距23磅图片部分需要单倍行距&#xff08;不然无法使用嵌入式&#xff09; 难点 文字和图片难以有效分离&#xff0c;无法分别设…