当前位置: 首页 > news >正文

实用调试技巧【下篇】

🔴本文章是在 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;//errorint* 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们多多支持哦🥰🥰🥰

请添加图片描述

相关文章:

实用调试技巧【下篇】

&#x1f534;本文章是在 Visual Studio 2022&#xff08;VS2022&#xff09;编译环境下进行操作讲解 文章目录3.2.调试的时候查看程序当前信息3.2.1.查看临时变量的值3.2.2.查看内存信息3.2.3.查看调用堆栈3.2.4.查看汇编信息&#x1f973;4.调试实例&#x1f973;5.如何写出&…...

【数据结构期末例题】

前言 本文是博主自己在准备学校数据结构考试时的总结&#xff0c;各个知识点都贴有对应的详细讲解文章以供大家参考&#xff1b;当然文中还有许许多多的截图&#xff0c;这些是博主对主要内容的摘取&#xff0c;对于那些基础较好的同学可以直接看截图&#xff0c;减少跳转对应文…...

管理物理和快照备数据库(Physical and Snapshot Standby Databases)

1&#xff0e;打开物理备数据库 物理备数据库可以打开做只读访问&#xff0c;用于从主数据库卸载查询负载。 如果已经购买Oracle Active Data Guard选项的授权&#xff0c;当数据库打开时Redo Apply可以是激活的&#xff0c;因此允许查询返回与从主数据库返回的完全相同的结果…...

双目立体视觉:SAD算法

算法原理SAD(Sum of absolute differences)是一种图像匹配算法。基本思想&#xff1a;差的绝对值之和。此算法常用于图像块匹配&#xff0c;将每个像素对应数值之差的绝对值求和&#xff0c;据此评估两个图像块的相似度。该算法快速、但并不精确&#xff0c;通常用于多级处理的…...

海外问卷调查答题技巧,纯干货分享,新手小白看过来

海外问卷调查为什么别人赚得盆满钵满而我却连通过都不行&#xff1f;是不是经常有人发出这种疑问&#xff0c;东哥作为一个结交过很多做问卷调查行业的跨境人士&#xff0c;也了解到很多做这一行的去答题的时候都是掌握一定技巧的&#xff0c;而不是去乱答。今天东哥就来说说国…...

【NGINX入门指北】Nginx Web 架构实验

Nginx Web 架构实验 文章目录Nginx Web 架构实验一、动态网站结构二、LNMP 动态网站环境部署三、fastcgi & php-fpm&#xff1a;四、php-fpm初始化配置五、Nginx Location、六、Nginx Rewrite七、CA&HTTPS八、Nginx 的平滑升级一、动态网站结构 资源 资源文件识别——…...

rtt-nano移植

nano其他功能移植 添加finsh组件打开宏实现rt_hw_console_getchar函数添加finsh组件到工程总结问题1. 移植到stm32G0过程中出现Undefined symbol rt_hw_interrupt_disable (referred from clock.o)??2. “implict declaration of function ‘ ‘ is invalid in c99??3. 关于…...

cnn+transformer

好的,下面是使用 Transformer 加 CNN 实现语义分割的代码,使用的数据集是 Semantic Segmentation Drone Dataset。 首先,我们需要导入必要的 Python 库和模块。我们将使用 PyTorch 深度学习框架来实现模型: #python import torch import torch.nn as nn import torch.nn.fu…...

Python fileinput模块:逐行读取多个文件

前面章节中&#xff0c;我们学会了使用 open() 和 read()&#xff08;或者 readline()、readlines() &#xff09;组合&#xff0c;来读取单个文件中的数据。但在某些场景中&#xff0c;可能需要读取多个文件的数据&#xff0c;这种情况下&#xff0c;再使用这个组合&#xff0…...

Vue3路由传参

vue3路由和vue2差别不是很大&#xff0c;不过在传参形式上略有改变 在Vue3中使用路由必须引入 useRouter 和 useRoute import { useRoute, useRouter } from vue-routerconst Router useRouter() //跳转const Route useRoute() //获取到值 同Vue2一样&#xff0c;query使用p…...

用户管理——认证功能JWT和Session

目录用户认证功能的技术选型JWT和Session的区别基于JWT和Session的认证流程基于JWT的认证流程基于Session的认证流程基于JWT和Session的认证的优缺点基于JWT和Session的认证的安全性基于JWT和Session的认证的性能分析基于JWT的一次性和无法废弃基于JWT和Session的认证的续签选择…...

hashlib — 加密哈希算法

hashlib — 加密哈希算法 1.概述 加密可以保护消息的安全&#xff0c;以便验证它们的准确性并且使它们受保护不被拦截。 Python 的加密方式支持包括利用像 MD5 和 SHA 这样的标准算法对消息内容产生签名的 hashlib 和验证消息没有在传输过程中被改变的 hmac hashlib 哈希库模…...

四喜临门选股预警源码指标

{四喜临门选股预警} AP1:CROSS(MA(C,5),MA(C,10)); RSV:(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100; K:SMA(RSV,3,1); D:SMA(K,3,1); AP2:CROSS(K,D); DIFF:EMA(CLOSE,12) - EMA(CLOSE,26); DEA:EMA(DIFF,9); AP3:CROSS(DIFF,DEA); AP4:CROSS(MA(V,5),MA(V,10)); GYTJ1:…...

Kotlin新手教程五(扩展)

一、扩展 在Kotlin中可以给一个类添加一个新的方法而不用继承该类或者使用设计模式&#xff0c;这样的方法称为扩展。 1.扩展函数 声明一个扩展函数&#xff0c;我们需要用一个 接收者类型 也就是被扩展的类型来作为他的前缀。 下面代码为 MutableList 添加一个swap 函数&am…...

QT入门Containers之Widget、Frame

目录 一、QWidget界面相关 1、布局介绍 2、基本界面属性 3、特殊属性 二、QFrame 三、Demo展示 此文为作者原创&#xff0c;创作不易&#xff0c;转载请标明出处&#xff01; 一、QWidget界面相关 1、布局介绍 为什么将QWidget容器放在第一个&#xff0c;因为目前使用过…...

数据结构与算法基础-学习-12-线性表之顺序队

一、个人理解队列是线性表的衍生之一&#xff0c;具有先进先出的特性&#xff0c;在队尾进行插入操作&#xff0c;在队头进行删除操作。队列的存储结构分为两个大类&#xff0c;一种是顺序队&#xff0c;就是用数组实现。另一种就是链队&#xff0c;使用链表实现。顺序队存在真…...

Python 字典(Dictionary)小窍门

字典是另一种可变容器模型&#xff0c;且可存储任意类型对象。字典的每个键值 key:value 对用冒号 : 分割&#xff0c;每个键值对之间用逗号 , 分割&#xff0c;整个字典包括在花括号 {} 中 ,格式如下所示&#xff1a;d {key1 : value1, key2 : value2 }注意&#xff1a;dict …...

知识图谱构建技术综述

摘要 *知识图谱为实现语义化智能搜索以及知识互联打下了基础&#xff0c;。&#xff0c; *随着知识的发展&#xff0c;传统的基于模板和规则构建的知识图谱已经被深度学习所替代。 知识组织得原则中&#xff1a;知识的充分性、有序性和标准化规则。深度学习的效果在很大程度上…...

环境变量和进程地址空间

目录 环境变量&#xff1a; env&#xff1a;显示所有的环境变量&#xff1a; echo $环境变量名表示查看环境变量的值 理解环境变量&#xff1a; getenv&#xff1a;显示环境变量的值 export set命令&#xff1a;显示所有变量 unset取消变量&#xff1a; pwd&#xff1a;当…...

【数据结构】栈和队列

目录 一、栈 1、栈的定义 2、栈的模拟实现&#xff08;顺序栈&#xff09; 1、创建一个顺序结构的栈 2、实现压栈方法&#xff08;push&#xff09; 3、模拟实现pop方法&#xff08;出栈&#xff09; 4、模拟实现peek(查看) 5、测试上述方法 3、栈的应用场景 1、改变元…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...