C语言入门知识——(7)VS2022的C语言基础调试

news2024/11/25 2:49:07

1、什么是bug

这个故事很多人都知道

1947年9月9日:第一个“Bug”被发现的时候:“1949年9月9日,我们晚上调试机器的时候,开着的窗户没有纱窗,机器闪烁的亮光几乎吸引来了世界上所有的虫子。果然机器故障了,我们发现了一只被继电器拍死的飞蛾,翅膀大约4英寸。”

第一次被发现的导致计算机错误的飞蛾,也是第一个计算机程序错误,而bug这个名词也被延用至今。

2、调试是什么

(1)调试的概念

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

(2)调试的基本步骤

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

(3)拒绝迷信调试

3、debug和release

(1)两者的概念

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

(2)Debug和Release的区别

  • 文件区别:Debug和Release模式下,会在项目文件里面各自生成一个Debug和Release文件
  • 反汇编区别:他们两个的反汇编代码有着明显差别,一般来说Debug比Release多
  • 内存区别:由于Debug包含了调试信息,所以会比release的内存要大
  • 应用区别:Debug用于程序员调试,release交予测试员和用户使用
  • 运行区别:release会在一定程度上对代码进行优化,这也是其内存较小的原因之一

(3)以下代码的运行在Debug和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;
}

4、windows环境调试介绍

Linux中的调试工具是gdb

(1)模式调整

必须要在Debug模式中才能使得代码正常调试

(2)VS快捷键

  • F5启动调试,经常用来直接跳到下一个断点处
  • shift+F5取消调试,在不想调试的时候可以用这个功能停止调试
  • ctrl+F5开始执行不调试,如果你想要程序直接跑起来而不调试就可以直接使用
  • F9创建/取消断点,断点可以使程序在想要的位置任意停止,继而一步步执行下去(在循环语句中尤其好用)
  • F10逐过程,通常用来处理一个过程,一个过程可以是一次函数调用或者一条语句
  • F11逐语句,就是每次都执行语句,这个快捷键可以使得我们的执行逻辑进入函数内部(是最为常用的快捷键),执行调试比较细一点
  • 更多快捷键

(3)调试窗口

  • 查看临时变量的值(监视):在vs2022调试状态下----窗口----监视

    • 一个小技巧,如果是监视指针,将格式写为【指针,数字】就可查看该指针后面指针的值
  • 查看内存信息:在vs2022调试状态下----窗口----内存

  • 查看调用堆栈:在vs2022调试状态下----窗口----调用堆栈

    • 通过调用堆栈可以清晰反应函数的调用关系以及当前调用所处的位置
    • 这个涉及到数据结构的栈
  • 查看汇编信息

    • 第一种查看方法:调试开始之后右键代码,选择“转到反汇编”
    • 第二种查看方法:在vs2022调试状态下----调试----窗口----反汇编
  • 查看寄存器信息:在vs2022调试状态下----调试----窗口----寄存器

    • 通过寄存器窗口可以看到当前运行环境的寄存器运行信息
    • 如果记住寄存器的名字还可以在监视窗口里面查看寄存器的
  • 查看自动窗口:在vs2022调试状态下----调试----窗口----自动窗口

    • 会自动添加、自动取消添加一些变量的信息
  • 查看局部变量:在vs2022调试状态下----调试----窗口----局部变量

5、一些调试的实例

(1)实例1:实现代码:求 1!+2!+3! …+ n! ,不考虑溢出

int main()
{
    int i = 0;
    int sum = 0;//保存最终结果
    int n = 0;
    int ret = 1;//保存n的阶乘
    scanf("%d", &n);
    for(i=1; i<=n; i++)
    {
        int j = 0;//问题在这里的上一步没有加上ret = 1;
        for(j=1; j<=i; j++)
        {
            ret *= j;
        }
        sum += ret;
    }
    printf("%d\n", sum);
    return 0;
}//这时候我们如果3,期待输出9,但实际输出的是15。

(2)实例2:研究程序死循环/异常终止的原因

#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模式下就会停止,这就是优化导致的
//比如在我的vs2022中,x86是死循环的,x64是在结尾终止的

6、如何写出易于调试的代码?

(1)优秀的代码

  • 代码运行正常
  • bug很少
  • 效率高
  • 可读性高
  • 可维护性高
  • 注释清晰
  • 文档齐全

当然还有很多很多类似的比较体系化的技巧。

(2)常见的编码技巧

  • 使用assert
  • 尽量使用const
  • 养成良好的编码风格
  • 添加必要的注释
  • 避免编码的陷阱

(3)const的作用

使得变量具有常属性,可以让代码具有鲁棒性、健壮性,能够应对一些异常的情况

int main()
{
    const int m = 100;
    const int * p = &m;
    const int ** pp = &p;
    int *** ppp = &pp;
    ***ppp = 200;
    printf("%d\n", m);
    return 0;
}
#include <stdio.h>
//代码1
void test1()
{
    int n = 10;
    int m = 20;
    int *p = &n;
    *p = 20;//ok?
    p = &m; //ok?
}
void test2()
{
    //代码2
    int n = 10;
    int m = 20;
    const int* p = &n;
    *p = 20;//ok?
    p = &m; //ok?
}
void test3()
{
    int n = 10;
    int m = 20;
    int *const p = &n;
    *p = 20; //ok?
    p = &m;  //ok?
}
int main()
{
    //测试无cosnt的
    test1();
    //测试const放在*的左边
    test2();
    //测试const放在*的右边
    test3();
    return 0;
}

(4)模拟strcpy函数

①官方库里的写法

/***
*char *strcpy(dst, src) - copy one string over another
*
*Purpose:
*       Copies the string src into the spot specified by
*       dest; assumes enough room.
*
*Entry:
*       char * dst - string over which "src" is to be copied
*       const char * src - string to be copied over "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*******************************************************************************/
char * strcpy(char * dst, const char * src)//(目的数组,源头数组)
{
    char * cp = dst;
    assert(dst && src);
    while(*cp++ = *src++)
        ;     /* Copy src over dst */
    return (dst);
}//其函数就是将一个字符串数组的内容拷贝到另外一个字符串数组中

②自己定义的写法

//方法一:
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)
{
    //断言,或者改成assert(dest && src)
    assert(dest != NULL);
    assert(src != NULL);
    while(*dest++ = *src++)
    {
        ;
    }
}
//方法四:
void my_strcpy(char* dest, char* src)
{
    //断言,或者改成assert(dest && src)
    assert(dest != NULL);
    assert(src != NULL);
    while(*dest++ = *src++)
    {
        ;
    }
}
//方法五:
char* my_strcpy(char* dest, char* src)
{
    assert(dest && src);
    char* ret = dest;
    while(*dest++ = *src++);
    return ret; 
}

(5)模拟strlen函数

#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
    int count = 0;
    assert(str);//assert(str != NULL);//断言的使用
    while(*str)//while (*str != '\0')
    {
        count++;
        str++;
    }
    return count;
}
int main()
{
    int len = my_strlen("abcdef");
    printf("%d\n", len);
    return 0;
}

7、编程常见的错误

  • 编译型错误:直接看错误提示信息(双击VS2022中的错误列表),解决问题。或者凭借经验就可以搞定。相对来说简单
  • 链接型错误:看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不存在或者拼写错误(一般会出现字眼“无法解析的外部命令”)
    在这里插入图片描述
  • 运行时错误:借助调试,逐步定位问题,最难搞

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

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

相关文章

Qt使用OpenGL进行多线程离屏渲染

基于Qt Widgets的Qt程序&#xff0c;控件的刷新默认状况下都是在UI线程中依次进行的&#xff0c;换言之&#xff0c;各个控件的QWidget::paintEvent方法会在UI线程中串行地被调用。若是某个控件的paintEvent很是耗时&#xff08;等待数据时间CPU处理时间GPU渲染时间&#xff09…

BI不是报表,千万不要混淆

商业智能BI作为商业世界的新宠儿&#xff0c;在市场上实现了高速增长并获得了各领域企业的口碑赞誉。 很多企业把商业智能BI做成了纯报表&#xff0c;二维表格的数据展现形式&#xff0c;也有一些简单的图表可视化。但是这些简单的商业智能BI可视化报表基本上只服务到了一线的…

【JAVA程序设计】【C00110】基于SSM(非maven)的车辆维修管理系统

基于SSM&#xff08;非maven&#xff09;的车辆维修管理系统项目简介项目获取开发环境项目技术运行截图项目简介 基于ssm框架非maven开发的车辆维修管理系统共分为三个角色&#xff1a;管理员、用户 管理员角色包含以下功能&#xff1a; 查看用户、添加用户、查看车辆信息、故…

FPGA纯verilog实现图像视频旋转 串口指令控制旋转角度 提供工程源码和技术支持

目录1、前言2、理论基础3、设计思路和框架图像输入和采集图像旋转处理图像缓存图像输出4、vivado工程详解5、上板调试验证6、福利&#xff1a;工程代码的获取1、前言 图像旋转是一种常用的图像处理技术&#xff0c;其基本原理就是指图像以某一点为中心旋转一定的角度&#xff…

函数的极限

目录 函数极限的定义&#xff1a; 数列的极限和函数极限 定理1&#xff1a; 自变量趋向有限制时&#xff0c;函数的极限 左右极限&#xff1a; 定理&#xff1a; 需要分左右极限求极限的三种问题&#xff1a; 例题&#xff1a; 例2&#xff1a; 极限性质&#xff1a; 保号…

WebRTC标准与框架解读(1)

1、如果让我来设计webrtc框架我在分析源码的时候&#xff0c;都喜欢做这样一件事情&#xff1a;如果让我来设计它&#xff0c;我会怎么做&#xff1f;大家可以紧跟我的思路&#xff0c;分析一下WebRTC为什么如此设计。为了对整个框架有有一个全面的了解&#xff0c;我们首先要做…

外包测试3年,离职后成功入职华为,拿到offer的那天我泪目了....

一提及外包测试&#xff0c;大部分人的第一印象就是&#xff1a;工作强度大&#xff0c;技术含量低&#xff0c;没有归属感&#xff01;外包工作三年总体感受就是这份工作缺乏归属感&#xff0c;心里总有一种落差&#xff0c;进步空间不大&#xff0c;接触不到核心技术&#xf…

IO详解(文件,流对象,一些练习)

目录 文件 文件概念 文件的路径 路径有俩种表示风格 文件类型 如何区分文本文件还是二进制文件? java对文件的操作 File类中的一些方法 流对象 流对象的简单概念 java标准库的流对象 1.字节流,(操作二进制数据的) 2.字符流 (操作文本数据的) 流对象最核心的四个…

Android Framework-进程间通信——Binder

我们知道&#xff0c;同一个程序中的两个函数之间能直接调用的根本原因是处于相同的内存空间中。 比如有以下两个函数A和B&#xff1a; /*Simple.c*/ void A() { B(); } void B() { }因为是在一个内存空间中&#xff0c;虚拟地址的映射规则完全一致&#xff0c;所以函数A和B之…

【JAVA程序设计】【C00111】基于SSM的网上图书商城管理系统——有文档

基于SSM的网上图书商城管理系统——有文档项目简介项目获取开发环境项目技术运行截图项目简介 基于ssm框架开发的网上在线图书售卖商城项目&#xff0c;本项目分为三种权限&#xff1a;系统管理员、卖家、买家 管理员角色包含以下功能&#xff1a; 用户信息管理、权限管理、订…

XSS跨站脚本

XSS跨站脚本XSS简介XSS验证XSS危害XSS简介 XSS被称为跨站脚本攻击(Cross-site scripting)&#xff0c;由于和CSS(Cascading Style Sheets)重名&#xff0c;所以改为XSS。XSS主要基于javascript语言完成恶意的攻击行为&#xff0c;因为javascript可以非常灵活的操作html、css和…

day57-day58【代码随想录】二刷数组

文章目录前言一、螺旋矩阵||&#xff08;力扣59&#xff09;二、螺旋矩阵&#xff08;力扣54&#xff09;三、顺时针打印矩阵&#xff08;剑指 Offer29&#xff09;四、在排序数组中查找元素的第一个和最后一个位置&#xff08;力扣34&#xff09;【二分查找】五、有多少小于当…

自动驾驶决策概况

文章目录1. 第一章行为决策在自动驾驶系统架构中的位置2. 行为决策算法的种类2.1 基于规则的决策算法2.1.1 决策树2.1.2 有限状态机&#xff08;FSM&#xff09;2.1.3 基于本体论&#xff08;Ontologies-based&#xff09;2.2 基于统计的决策算法2.2.1 贝叶斯网络&#xff08;B…

智慧制硅厂 Web SCADA 生产线

我国目前是全球最大的工业硅生产国、消费国和贸易国&#xff0c;且未来该产业的主要增量也将来源于我国。绿色低碳发展已成为全球大趋势和国际社会的共识&#xff0c;随着我国“双碳”目标的推进&#xff0c;光伏产业链快速发展&#xff0c;在光伏装机需求的带动下&#xff0c;…

flink兼容性验证

flink介绍&#xff1a;https://blog.csdn.net/weixin_43563705/article/details/107604693 一、安装启动 安装flink及其依赖 yum install java-1.8.0-openjdk curl tar mkdir -p /usr/local/flink wget https://mirrors.aliyun.com/apache/flink/flink-1.16.1/flink-1.16.1-bi…

如何校招进BAT做产品经理

嗨&#xff0c;很高兴&#xff0c;以文字的形式和你见面。在校招中&#xff0c;我拿到了百度、京东、爱奇艺、新浪和去哪儿的产品经理校招offer&#xff0c;其中百度是special offer。在找实习的过程中&#xff0c;也拿到了爱奇艺、微信电影票、搜狐畅游、艺龙等公司的产品经理…

Ac4GlcNAz,98924-81-3,N-乙酰葡糖胺叠氮基,可以进行糖化学修饰

Ac4GlcNAz反应特点&#xff1a;四乙酰氨基叠氮氨基葡萄糖&#xff08;Ac4GlcNAz&#xff0c;98924-81-3&#xff09;为糖缀合物可视化提供非放射性替代物。西安凯新生物科技有限公司供应的解释道它是细胞通透性、细胞内处理和结合的&#xff0c;而不是其天然单糖对乙酰氨基葡萄…

CEC2017:斑马优化算法(Zebra Optimization Algorithm,ZOA)求解cec2017(提供MATLAB代码)

一、斑马优化算法 斑马优化算法&#xff08;Zebra Optimization Algorithm&#xff0c;ZOA&#xff09;Eva Trojovsk等人于2022年提出&#xff0c;其模拟斑马的觅食和对捕食者攻击的防御行为。 斑马因身上有起保护作用的斑纹而得名。没有任何动物比斑马的皮毛更与众不同。斑…

SpringCloud的基本使用

文章目录一.单体架构和分布式架构的区别1.单体架构2.分布式架构二.微服务1.微服务的架构特征2.微服务技术对比3.企业需求4.微服务的远程定义5.提供者与消费者三.Eureka注册中心1.eureka的作用2.搭建EurekaServer3.Eureka注册3.服务拉取四.Ribbon负载均衡1.负载均衡流程2.负载均…

总被程序员坑?你需要了解API接口

编辑导读&#xff1a;程序员是公司里的技术岗&#xff0c;也是产品经理最密切的合作伙伴。但是&#xff0c;程序员能看懂产品经理的工作&#xff0c;产品经理却不一定能明白程序员的工作&#xff0c;因此也常常被无良程序员坑。本文就从API接口的维度&#xff0c;浅析API的概念…