实用调试技巧【下篇】

news2024/11/15 12:40:59

🔴本文章是在 Visual Studio 2022(VS2022)编译环境下进行操作讲解

文章目录

    • 3.2.调试的时候查看程序当前信息
      • 3.2.1.查看临时变量的值
      • 3.2.2.查看内存信息
      • 3.2.3.查看调用堆栈
      • 3.2.4.查看汇编信息
  • 🥳4.调试实例
  • 🥳5.如何写出(易于调试)的代码
    • 5.1.模拟实现库函数: strcpy
    • 5.2. const 修饰指针
  • 🥳6.编程常见的错误

请添加图片描述

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

3.2.1.查看临时变量的值

🔴自动窗口
👉调试–>窗口–>自动窗口
在这里插入图片描述
在这里插入图片描述
它会出现一个自动窗口,它会自动捕获变量的值,让你监视,方便的我们不用手动添加变量,但是如果它不想让你看的时候过了一会就会自动取消了,我们就监视不到了
🔴局部变量
👉在自动窗口的下面
在这里插入图片描述
与自动窗口比较相似,但不同的是放的是局部变量,监视的是程序执行中的局部变量
🔴监视
👉调试–>窗口–>监视
在这里插入图片描述
这才是我们用到最多的调试功能
在这里插入图片描述
我们想监视谁,就输入谁,它不会自己取消,会一直显示,来为我们提供对变量的监视
在这里插入图片描述
在这里插入图片描述
数组也可以观察,变量的地址也都可以观察到
如果有需要,可以同时打开4个监视窗口,每个窗口都可以拖动,放到你想放的位置

3.2.2.查看内存信息

🔴内存
👉调试–>窗口–>内存
在这里插入图片描述
在这里插入图片描述
☝️内存中本放的是二进制的数据,但是为了展示方便,所以是以十六进制来显示的☝️

3.2.3.查看调用堆栈

🔴调用堆栈
👉调试–>窗口–>调用堆栈
在这里插入图片描述
👇简单知道一下 什么是栈👇
在这里插入图片描述

👇看这段代码👇
在这里插入图片描述
👇调用堆栈👇
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
☝️反映的是函数的调用逻辑☝️

3.2.4.查看汇编信息

🔴反汇编
👉在内存的下面
在这里插入图片描述
👇看到的是c语言代码翻译出来的汇编代码👇
在这里插入图片描述

🥳4.调试实例

👇看下面这段代码👇

#include<stdio.h>

int main()
{
	int i = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

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

	return 0;
}

运行起来是什么样呢?
在这里插入图片描述
数组已经越界了,为什么没有崩溃而是死循环了呢?
👇进入调试👇
在这里插入图片描述
i 等于9的时候一切都正常,我们继续👇
在这里插入图片描述
这个代码真的是在越界访问!胆大包天啊,如果我们继续下一步呢👇
在这里插入图片描述
继续一直执行
在这里插入图片描述
再改
在这里插入图片描述
i 到12之后并没有++变成13, i 再一直跟着 arr[12] 改变,陷入了死循环,这是为什么呢?有没有可能它们是在同一个空间呢?我们看一下👇
在这里插入图片描述
地址居然一摸一样,它俩在一个空间😕
那么底层原理什么呢?为什么会这样呢?👇

🔴原理:
1. i 和 arr 是局部变量,局部变量是放在栈区上的
2. 栈区内存的使用习惯是 使用高地址的空间,再使用低地址处的空间
3. 数组随着下标的增长,地址是由低到高变化的

在这里插入图片描述

🥳5.如何写出(易于调试)的代码

🥰优秀的代码:

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

🥰常见的coding技巧:

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

5.1.模拟实现库函数: strcpy

在这里插入图片描述
拷贝一个字符串
示例👇

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	strcpy(arr2, arr1);
	printf("%s\n", arr2);

	return 0;
}

在这里插入图片描述

👇模拟实现 strcpy👇

#include<stdio.h>
#include<string.h>
void my_strcpy(char* dest, char* src)
{
	while (*src != 0)
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src; // \0的拷贝
}
int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	my_strcpy(arr2, arr1);
	printf("%s\n", arr2);

	return 0;
}

如果写成这样的代码,这算一个好的代码吗?当然不算一个好的代码,我们可以优化一下👇

void my_strcpy(char* dest, char* src)
{
	while (*src != 0)
	{
		*dest++ = *src++;
	}
	*dest = *src; // \0的拷贝
}

我们还可以再融合一下👇

void my_strcpy(char* dest, char* src)
{
	while (*dest++ = *src++)
	{
		;
	}
}

可以直接一次搞定
这样改进完好像已经足够好了,但是我们还能再改进👇

void my_strcpy(char* dest, char* src)
{
	if (dest == NULL || src == NULL)
	{
		return;
	}
	while (*dest++ = *src++)
	{
		;
	}
}

防止遇到空指针,但是这样处理遇到问题只是回避掉了,并不做处理👇

#include<stdio.h>
#include<string.h>
#include<assert.h>
void my_strcpy(char* dest, char* src)
{
	//断言
	assert(dest != NULL);
	assert(src != NULL);

	while (*dest++ = *src++)
	{
		;
	}
}
int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	my_strcpy(arr2, NULL);
	printf("%s\n", arr2);

	return 0;
} 

在这里插入图片描述
使用断言处理之后,如果有问题它就会报错,把问题抛出来并且告诉你出错在哪里,如果不使用断言执行程序的话代码就崩掉了,不会告诉你哪里有问题👇
在这里插入图片描述
🚨断言是对程序员非常友好的东西,我们使用断言是个很好的编程习惯
🚨使用断言别忘记引用头文件 <assert.h>

void my_strcpy(char* dest, char* src)
{
	//断言
	assert(dest && src);

	while (*dest++ = *src++)
	{
		;
	}
}

简便一点可以直接写成这样☝️

5.2. const 修饰指针

在这里插入图片描述
const修饰变量m之后,m的值就更改不了了
但是可以使用一些小聪明把m改掉👇

int main()
{
	const int m = 10;
	//m = 20;//error
	int* p = &m;
	*p = 20;
	printf("%d\n", *p);

	return 0;
}

在这里插入图片描述
这个代码非常奇葩,因为 const 只是在语法层面限制了m不能改,但是通过地址是可以更改的
我们可以在语法层面把指针p 也进行限制👇
在这里插入图片描述

int main()
 {
	int n = 100;
	const int m = 10;
	//m = 20;//error
	//const 修饰指针
	//1. const放在*的左边,*p不能改了,也就是p指向的内容,不能通过p来改变了。但是p是可以改变的,p可以指向其他变量
	const int* p = &m;
	p = &n;

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

	return 0;
 } 

在这里插入图片描述

int main()
 {
	int n = 100;
	const int m = 10;
	//m = 20;//error
	//const 修饰指针
	//2. const放在*的右边,限制的是p,p不能改变,但是p指向的内容*p,是可以通过p来改变的
	int* const p = &m;
	*p = n;

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

	return 0;
 } 

在这里插入图片描述

🤜 1. const放在的左边,p不能改了,也就是p指向的内容,不能通过p来改变了。但是p是可以改变的,p可以指向其他变量
🤜2. const放在的右边,限制的是p,p不能改变,但是p指向的内容p,是可以通过p来改变的

void my_strcpy(char* dest,const char* src)
{
	//断言
	assert(dest && src);

	while (*dest++ = *src++)
	{
		;
	}
}

所以上面模拟实现strcpy的代码这样写就更严谨了,加上了 const 来修饰char* src
🥰提高了代码的健壮性(鲁棒性)
因为如果下面的 *dest++ = *src++ 位置要是不小心写反了程序就会报错,所以这样写才是有意义的!

我们再来进行最后一次优化👇

#include<stdio.h>
#include<string.h>
#include<assert.h>

//strcpy函数返回的是目标空间的起始位置
char* my_strcpy(char* dest,const char* src)
{
	//断言-- 保证指针的有效性
	assert(dest && src);
	char* ret = dest;
	//把src指向的字符串拷贝到dest指向的数组空间,包括\0字符
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[] = "hello world";
	char arr2[20] = { 0 };
	//链式访问
	printf("%s\n", my_strcpy(arr2, arr1));

	return 0;
} 

🥰这些都是一些技巧,希望大家可以理解🥰

🥳6.编程常见的错误

🥰优秀的代码:

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

🚨做个用心的人!积累排错经验!

总结🥰
本文章是在 Visual Studio 2022(VS2022)编译环境下进行操作讲解
以上就是调试技巧下篇内容啦🥳🥳🥳🥳
希望我们可以做一个用心的人💕💕💕
小的会继续学习,继续努力带来更好的作品😊😊😊
创作写文不易,还多请各位大佬uu们多多支持哦🥰🥰🥰

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【笔记】数据异常检测与修复总结

文章目录一、异常种类1. 对于移动对象的数据异常2. 对于时序数据的异常检测二、异常数据清洗流程三、数据预处理四、异常检测算法五、异常修复算法六、漂移数据清洗一、异常种类 不同的研究对象&#xff0c;有着不同的异常分类方式 1. 对于移动对象的数据异常 异常数据信息&…

leaflet: 数据聚合,显示当前bounds区域中的点的名称列表(078)

第078个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中实现数据聚合的功能 ,左边列出右边可视区域内的marker的名称。这里主要用到了可视区域的范围以及contains函数。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方…

windows11安装sqlserver2022报错

window11安装SQL Server 2022 报错 糟糕… 无法安装SQL Server (setup.exe)。此 SQL Server安装程序介质不支持此OS的语言&#xff0c;或没有SQL Server英语版本的安装文件。请使用匹配的特定语言SQL Server介质;或安装两个特定语言MUI&#xff0c;然后通过控制面板的区域设置…

深入浅出带你学习weblogic中间件常见漏洞

前文 上一篇文章给大家带来了JBOSS中间件漏洞的利用知识&#xff0c;不知道大家学习的如何了&#xff0c;今天给大家带来的是一个比较重要的中间件——weblogic漏洞利用的介绍&#xff0c;按我们之前的顺序&#xff0c;先学习一下什么是WEBLOGIC中间件。 什么是WebLogic? We…

机器学习:Recurrent Neural Network-RNN

应用举例 如果有很多词汇的时候&#xff0c;one-encode会导致很长&#xff0c;可以将不常见的归类到other&#xff0c;也可以用n-gram进行编码 输出的是一个概率分布 相同的词得到不同的结果&#xff0c;需要网络具有记忆&#xff0c;RNN网络的设计就是使得网络具有部分的记忆能…

【Python入门第十一天】Python 运算符

Python 运算符 运算符用于对变量和值执行操作。 Python 在以下组中划分运算符&#xff1a; 算术运算符赋值运算符比较运算符逻辑运算符身份运算符成员运算符位运算符 Python 算术运算符 算术运算符与数值一起使用来执行常见的数学运算&#xff1a; 运算符&#xff1a; 名…

动态网站开发讲课笔记01:网页开发基础

文章目录零、本讲学习目标一、HTML基础&#xff08;一&#xff09;HTML简介1、HTML2、HTML语言的基本格式3、<!DOCTYPE>声明4、html标签5、head标签6、body标签7、编写第一个网页8、关于编写HTML文件的工具9、HTML标签概述&#xff08;1&#xff09;单标签&#xff08;2&…

【论文笔记】图像修复Learning Joint Spatial-Temporal Transformations for Video Inpainting

论文地址&#xff1a;https://arxiv.org/abs/2007.10247 源码地址&#xff1a;GitHub - researchmm/STTN: [ECCV2020] STTN: Learning Joint Spatial-Temporal Transformations for Video Inpainting 一、项目介绍 当下SITA的方法大多采用注意模型&#xff0c;通过搜索参考帧…

webpack 开发环境的基本配置(webpack打包样式资源、html、图片、devserver、开发环境配置、以及其他资源)

A.打包样式资源 1. 创建文件 2. 下载安装 loader 包 npm i css-loader style-loader less-loader less -D 3. 修改配置文件 /*webpack.config.js webpack的配置文件作用: 指示 webpack 干哪些活&#xff08;当你运行 webpack 指令时&#xff0c;会加载里面的配置&#xff…

计算机图形学(Computer Graphics)的学习笔记

目录 1.计算机图形学是什么 2.计算机图形学学什么 3.计算机图形学应用举例 4.计算机图形学主要内容 5.图形的分类 6.图形要素 7.图形的表达方式 8.图形学应用生活中的例子 9.计算机图形学定义 10.用户界面发展方向 11.影视中的变形技术要点 12.虚拟现实的一些技术 …

Python 之 Matplotlib xticks 的再次说明、图形样式和子图

文章目录一. 改变 x 轴显示内容 xticks 方法再次说明1. x 轴是数值型数据2. 将 x 轴更改为字符串3. 总结二. 其他元素可视性1. 显示网格&#xff1a;plt.grid()2. plt.gca( ) 对坐标轴的操作三. plt.rcParams 设置画图的分辨率&#xff0c;大小等信息四. 图表的样式参数设置1. …

CUDA C++扩展的详细描述

CUDA C扩展的详细描述 文章目录CUDA C扩展的详细描述CUDA函数执行空间说明符B.1.1 \_\_global\_\_B.1.2 \_\_device\_\_B.1.3 \_\_host\_\_B.1.4 Undefined behaviorB.1.5 __noinline__ and __forceinline__B.2 Variable Memory Space SpecifiersB.2.1 \_\_device\_\_B.2.2. \_…

汽车改装避坑指南:大尾翼

今天给大家讲一个改装的误区&#xff1a;大尾翼 很多车友看到一些汽车加了大尾翼&#xff0c;非常的好看&#xff0c;就想给自己的车也加装一个。 那你有没有想过&#xff0c;尾翼这东西你真的需要吗&#xff1f; 赛车为什么加尾翼&#xff1f;尾翼主要是给车尾部的一个压低提供…

三维重建基础入门之特征点检测基础(二)

前言&#xff1a;本文着眼于记录自己从普通CVer入门三维重建的学习过程&#xff0c;可能过程比较坎坷&#xff0c;都在摸索阶段&#xff0c;但争取每次学习都能进一步&#xff0c;提高自己的能力&#xff0c;同时&#xff0c;每篇文章都会按情况相应地推出B站讲解视频&#xff…

在群晖上体验维格表社区版APITable

本文是应网友 lee yong 和 shijie880500 的要求折腾的&#xff1b; 什么是 APITable &#xff1f; APITable 是 vika 维格表的社区版&#xff0c;是一个面向 API 且易于使用的可视化数据库&#xff0c;适合所有人&#xff0c;使其成为 Airtable 的最佳开源替代品。最重要的是&a…

智慧城市总体解决方案和建设思路

“智慧城市”是综合城市发展规划、城市运行管理、城市经济社会发展、新一代信息技术应用等为一体的城市发展新模式&#xff0c;是促进城市科学发展、跨越发展、和谐发展的必然选择&#xff0c;是提升现代城市综合竞争力和国际影响力的战略制高点。 建设智慧城市&#xff0c;是城…

电脑文件被删除?试了十几款工具,数据恢复大师只看这一款

长期使用电脑办公&#xff0c;电脑肯定保存着很多数据文件。文件一多&#xff0c;我们势必是要进行整理的。要不文件太多会占用内存&#xff0c;还会影响电脑的运行速度。 整理过程中&#xff0c;重要的电脑文件被误删了怎么办&#xff1f;建议您先使用常规的方法来进行操作先…

双目客流统计方案的应用原理

双目客流统计客流摄像头采用立体视觉技术实现高度统计功能。基于视差原理。利用双镜头摄取的两幅图像的视差&#xff0c;构建三维场景&#xff0c;在检测到运动目标后。通过计算图像对应点间的位置偏差。获取目标的三维信息&#xff0c;在深度图像中对目标的检测与追踪&#xf…

Java基础二

目录 1. 常见类和对象 1.1 object 1.2 数组 Array 1.3 二维数组 1.6 二分查找法 1.7 字符串 1.8 包装类 1.9 日期类 1.10 工具类 1.11 比较 2. 异常 2.1介绍 2.2 基础语法 2.3 常见异常 3. 集合 3.1 介绍 3.2 常用的接口和类 3.3 ArrayList 基本操作 3.4 ArrayL…

165、【动态规划】leetcode ——337. 打家劫舍 III:记忆化递归+动态规划(C++版本)

题目描述 原题链接&#xff1a;337. 打家劫舍 III 解题思路 &#xff08;1&#xff09;记忆化递归 采用后序遍历的方式&#xff0c;设置一个unordered_map型Hash表record&#xff0c;记录每个结点的情况。当遍历到该节点时&#xff0c;判定之前是否遍历过&#xff0c;如果遍…