vs 调试

常用:

调试->窗口->

                      断点

                      监视

                      自动窗口

                      局部变量

                      调用堆栈

                      内存

                      反汇编(也可以右键,转到反汇编)

                      寄存器

快捷键:

F5:启用调试,经常用来跳到下一个断点处

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

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

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

Crtl+F5:开始执行不调试

一些调试的实例:
实例1:

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

所以正确的代码就应该是

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
int main()
{
	int i = 0;
	int n = 0;
	scanf("%d", &n);
	int sum = 0;
	int ret = 1;
	for (i = 1;i <= n;i++)
	{
		ret = 1;
		int j = 0;
		for (j = 1;j <= i;j++)//计算i!
		{
			ret *= j;//经过调试我们可以发现ret的值会在程序进行中改变,而我们希望每次计算n!的时候ret初始化为1,所以应该在函数内部定义ret
		}
		sum += ret;//i从1到n的阶乘相加
	}
	printf("%d\n", sum);
	return 0;
}

 实例2:
研究程序死循环的原因

我们观察程序,分析为什么会死循环打印hello world

(以上结果演示是在vs编译器的x86环境下,不同编译器,预留空间不同)

在调试过程中我们可以发现arr[12]的值始终是和i的值相等的,那么这是为什么呢,可能是他们占了同一块内存空间,我们将他们的地址取出观察发现确实占的是同一块内存空间,等i自增到12是,将arr[12]这块空间赋值为10,在重复,i永远不可能大于12,所以死循环打印hello world。

原因:局部数据在栈区中存放,而栈区内存的使用习惯是先使用高地址处的空间,在使用低地址处的空间。但是数组地址随着下标的增长是由低到高变化的。所以如果i和arr之间有适当的空间,那么利用数组的越界操作就有可能会覆盖到i,导致死循环出现。

(这类题目,在《C陷阱和缺陷》书籍中提到)

如果是release版本的话,就会对上面的代码,做出适当的优化,打印结果在这题中会打印出12个hello world。

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

如何写出好的代码

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

常见技巧

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

例:模拟实现strcpy函数

 我们可以初步写一个这样的代码,但是这个代码还有许多地方可以优化

void my_strcpy(char*dest, char*src)//destination目标空间,source源数据
{
	while (*src != '\0')
	{
		*dest = *src;
		src++;
		dest++;
	}
	*dest = *src;//将\0,也拷贝过来
}

int main()
{
	char arr1[20];
	char arr2[] = "hello world";
	//strcpy再拷贝字符串的时候会把\0也拷进去,这边便于识别字符长度
	my_strcpy(arr1, arr2);//用一个strcpy函数实现将arr2里面的数据拷贝到arr1中
	return 0;
}

比如函数部分可以写为

void my_strcpy(char* dest, char* src)//destination目标空间,source源数据
{
	while (*dest++ = *src++)
	{
		;
	}
	
}

\0的ASCII码值是数字0,所以我们可以指将将其放在判断里面,后置++,先赋值后++,当判断是\0的时候再自增一次,就是想当于将\0的值也赋进去。

我们也可以将代码进一步优化,使用assert和const

#include<assert.h>
void my_strcpy(char* dest, const char* src)//destination目标空间,source源数据//加const src的值不能被改变,避免出现拷反的情况
{
	//断言(如果assert为假就报错,需要包含assert.h的头文件)
	assert(src != NULL);// 空指针不能直接使用,传参是不能对空指针进行解引用
	assert(dest != NULL);
	while (*dest++ = *src++)
	{
		;
	}
	
}

assert函数,表示断言如果assert为假,编译器就会报错,并能定位到错的位置,使用时需要包含assert.h的头文件。

const表示常变量,这个值不能被直接修改,但是我们可以通过他的地址找到这个数对其进行修改,如:

const修饰指针变量分为两种情况

  1. const放在*左边(如const int* p或者int const *p)意思是:p指向的对象不能通过p来改变了,但是p变量本身的值是可以改变的。
  2. const放在*右边(int* const p)意思是:p指向的对象是可以通过p来改变的,但是不能修改p变量本身的值
  3. 若两边都放(const int* const p)意思是:p指向的对象和p变量本身都不可通过p来改变。 

但是我们发现在库函数里,strcpy的返回值类型是char*,这是为什么呢?

是为了实现链式访问,strcpy函数返回的是目标空间的起始地址。

我们可以将代码进一步完善:

#include<stdio.h>
#include<assert.h>
//模拟实现strcpy函数

char* my_strcpy(char* dest, const char* src)//destination目标空间,source源数据//加const src的值不能被改变,避免出现拷反的情况
{
	//断言(如果assert为假就报错,需要包含assert.h的头文件)
	char* ret = dest;//在程序运行过程中dest的地址已经发生了改变,所以我们可以向将他的起始地址存起来。之后我们使用这个数据的时候就可以通过起始地址找到它
	assert(src != NULL);// 空指针不能直接使用,传参是不能对空指针进行解引用
	assert(dest != NULL);
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20];
	char arr2[] = "hello world";
	//strcpy再拷贝字符串的时候会把\0也拷进去,这边便于识别字符长度
	printf("%s\n",my_strcpy(arr1, arr2));//用一个strcpy函数实现将arr2里面的数据拷贝到arr1中
	return 0;
}

(《高质量C/C++编程》一书中最后章节试卷有关strlcpy模拟实现的项目 )

注意:

  1. 分析参数的设计(命名,类型),返回值类型的设计
  2. 野指针,空指针的危害
  3. assert的使用
  4. const的使用
  5. 注释的添加

模拟一个strlen函数:

#include<stdio.h>
#include<assert.h>
//模拟实现strlen函数
int my_strlen(const char* str)
{
	int count = 0;
	assert(str != NULL);//这里也可以直接写str
	while (*str != '\0')//这里也可以直接写*str
	{
		str++;
		count++;
	}

	return count;
}
int main()
{
	char arr[] = "hello world";
	printf("%d\n", my_strlen(arr));
	return 0;
}

 变成常见错误:

  • 编译型错误

(看错误提示信息,双击)

  • 链接型错误 

(一般是标示符名不存在,或者拼写错误,可以用 ctrl+F查看文本)

  • 运行时错误 

借助调试,一步步分析。 

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

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

相关文章

25. 深浅拷贝

一、什么是浅拷贝 只对对象的最顶层进行的拷贝称为 浅拷贝。我们可以用 copy 模块中的 copy() 方法实现浅拷贝。 import copya [11, 22, 33] b [44, 55, 66] c [a, b] d copy.copy(c)print(f"c: {c}") print(f"d: {d}") print(f"c d: {c d}&q…

docker简单命令

docker images 查看镜像文件 docker ps -a 查看容器文件 docker rm 0b2 删除容器文件&#xff0c;id取前三位即可 docker rmi e64 删除镜像文件&#xff08;先删容器才能删镜像&#xff09;&#xff0c;id取前三位即可 在包含Dockerfile文件的目录…

【Java】4、虚拟机 JVM

目录 Java内存区域详解(重点) JVM垃圾回收详解(重点) 类文件结构详解 类加载过程详解 类加载器详解(重点) 最重要的JVM参数总结 JDK监控和故障处理工具总结 JVM线上问题排查和性能调优案例 参考&#xff1a; JVM 核心技术 32 讲 深入浅出 Java 虚拟机

谷歌浏览器的无障碍功能介绍

在数字化时代&#xff0c;互联网已经成为人们生活中不可或缺的一部分。然而&#xff0c;并不是所有人都能平等地享受网络带来的便利。为了帮助有特殊需求的人士更好地访问和使用网络内容&#xff0c;谷歌浏览器推出了一系列无障碍功能。这些功能旨在提升视力障碍、听力障碍及其…

3D 生成重建035-DiffRF直接生成nerf

3D 生成重建035-DiffRF直接生成nerf 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 本文提出了一种基于渲染引导的三维辐射场扩散新方法DiffRF&#xff0c;用于高质量的三维辐射场合成。现有的方法通常难以生成具有细致纹理和几何细节的三维模型&#xff0c;并且容易出…

从斯柯达和大众汽车安全漏洞事件剖析谈软件安全设计

一、事件概述 2022年&#xff0c;斯柯达和大众汽车被曝出存在一系列安全漏洞&#xff0c;这一事件引起了广泛关注。据估算&#xff0c;这些漏洞可能涉及超过 140 万辆汽车&#xff0c;涵盖斯柯达速派 III&#xff08;Skoda Superb III&#xff09;、斯柯达柯珞克&#xff08;S…

Hyperledger Fabric 2.x 环境搭建

Hyperledger Fabric 是一个开源的企业级许可分布式账本技术&#xff08;Distributed Ledger Technology&#xff0c;DLT&#xff09;平台&#xff0c;专为在企业环境中使用而设计&#xff0c;与其他流行的分布式账本或区块链平台相比&#xff0c;它有一些主要的区别。 环境准备…

OpenIPC开源FPV之Adaptive-Link天空端代码解析

OpenIPC开源FPV之Adaptive-Link天空端代码解析 1. 源由2. 框架代码3. 报文处理3.1 special报文3.2 普通报文 4. 工作流程4.1 Profile 竞选4.2 Profile 研判4.3 Profile 应用 5. 总结6. 参考资料7. 补充资料7.1 RSSI 和 SNR 的物理含义7.2 信号质量加权的理论依据7.3 实际应用中…

metinfo的csrf漏洞复现

http://localhost/metinfo/install/index.php 管理员admin登录 抓修改信息包 进入点击受害链接 localhost/333.html 管理员被修改密码原来root错误被强制退出 输入密码123456登录正常

jclasslib Bytecode Viewer 安装

IDEA 2023.1.3 Settings->Plugins->Marketplace&#xff0c;搜索jclasslib Bytecode Viewer, install,apply 选中你所要分析的类&#xff0c;view->show bytecode with jclasslib gaoding

智能高效的IDE GoLand v2024.3全新发布——支持最新Go语言

GoLand 使 Go 代码的阅读、编写和更改变得非常容易。即时错误检测和修复建议&#xff0c;通过一步撤消快速安全重构&#xff0c;智能代码完成&#xff0c;死代码检测和文档提示帮助所有 Go 开发人员&#xff0c;从新手到经验丰富的专业人士&#xff0c;创建快速、高效、和可靠的…

Android学习路线图

‌Android系统的开发始于2003年&#xff0c;最初由安迪鲁宾在危险公司&#xff08;Danger, Inc.&#xff09;开发。2005年&#xff0c;Google收购了危险公司&#xff0c;并将其移动开发团队纳入旗下。2007年&#xff0c;Google正式发布了Android的第一个版本&#xff0c;并随后…

【含开题报告+文档+PPT+源码】基于微信小程序的旅游论坛系统的设计与实现

开题报告 近年来&#xff0c;随着互联网技术的迅猛发展&#xff0c;人们的生活方式、消费习惯以及信息交流方式都发生了深刻的变化。旅游业作为国民经济的重要组成部分&#xff0c;其信息化、网络化的发展趋势也日益明显。旅游论坛作为旅游信息交流和分享的重要平台&#xff0…

CTFshow-php特性(Web89-115)

CTFshow-php特性(Web89-115) Web89&#xff08;intval&#xff09; <?php include("flag.php"); highlight_file(__FILE__);if(isset($_GET[num])){$num $_GET[num];if(preg_match("/[0-9]/", $num)){die("no no no!");}if(intval($num))…

ip地址获取失败啥意思?ip地址获取失败怎么回事

在日常的网络使用中&#xff0c;我们时常依赖于稳定的IP地址来确保数据的顺畅传输和设备的正常识别。然而&#xff0c;有时我们会遇到“IP地址获取失败”的困扰&#xff0c;这不仅阻碍了我们的网络访问&#xff0c;还可能带来一系列的网络连接问题。那么&#xff0c;IP地址获取…

中国计算机学会计算机视觉专委会携手合合信息举办企业交流活动,为AI安全治理打开“新思路”

近期&#xff0c;《咬文嚼字》杂志发布了2024年度十大流行语&#xff0c;“智能向善”位列其中&#xff0c;过去一年时间里&#xff0c;深度伪造、AI诈骗等话题屡次登上热搜&#xff0c;AI技术“野蛮生长”引发公众担忧。今年9月&#xff0c;全国网络安全标准化技术委员会发布了…

RK3588, FFmpeg 拉流 RTSP, mpp 硬解码转RGB

RK3588 ,基于FFmpeg, 拉取RTSP,使用 mpp 实现硬解码. ⚡️ 参考: Rk3588 FFmpeg 拉流 RTSP, mpp 硬解码转RGBUbuntu x64 架构, 交叉编译aarch64 FFmpeg mppCode RTSPint open_stream(

ubuntu监测硬盘状态

安装smartmontools smartctl -l error /dev/sdk smartctl -i /dev/sda lshw -class disk smartctl -H /dev/sd 结果1&#xff1a; 结果2&#xff1a;PASSED&#xff0c;这表示硬盘健康状态良好 smartctl -a /dev/sdb sdk lsblk blkid 测试写入速度 time dd if/dev/zero of…

Yolov8源码分析

1、目录介绍 主要目录ultralitics&#xff08;重点&#xff09; 1、assets目录 这个文件保存了YOLO历史上可以说是最经典的两张图片&#xff0c;供大家测试程序来使用的。 2、cfg 这个文件下面保存了我们的模型配置文件&#xff0c;cfg目录是项目配置的集中地&#xff0c;其…

【学习笔记总结】华为云:应用上云后的安全规划及设计

一、背景和问题 数字化时代&#xff0c;随着信息技术的飞速发展&#xff0c;企业和各类组织纷纷将自身的应用程序迁移至云端。云计算凭借其诸多优势&#xff0c;如成本效益、可扩展性、灵活性以及便捷的资源共享等&#xff0c;已然成为了现代业务运营的重要支撑。 今年&#xf…