基于vs环境调试和优化代码的研究

简介: 基于vs环境调试和优化代码的研究

debug和release的区别

debug包含调试信息 文件通常都比release版本大

调试代码快捷键

实例1:数组越界访问

实例1代码在bebug版本下可能会死循环(不同编译器结果不同)

局部变量是在栈区上分配内存的

实例1中 i 和 arr 都是局部变量

1.栈区的默认使用:

先使用高地址处的空间 再使用低地址的空间

2.数组随着下标的增长 地址是由低到高的

根据这两条信息可以推断出 i 和 arr 在栈区上的相对位置

死循环解释:

1.i和数组arr都是局部变量 局部变量都是在栈区上使用的

且栈区是先使用高地址再使用低地址的空间 所以i会创建在比arr高的地址上

循环开始的时候 随着数组下标的增长 地址由低到高

在数组越界访问的时候 就有可能访问到i的地址 改变i的值 从而进入死循环

但在release版本下 此代码不会报错

原因:在debug模式下,变量的分配空间顺序与变量的声明顺序一致。先声明就先分配空间。

在release版本下,对数组进行了优化,会先分配数组的空间 也就是arr在高地址 i在低地址

也就不会发生数组越界访问到i的情况

解决方法:可以先声明数组然后再声明变量i

实例2:调用堆栈的使用

如图代码 main 函数 调用 test1函数 test1函数 调用test2函数

函数的调用也是在栈上开辟空间的

调用堆栈:像栈一样的形式来展示函数调用的逻辑

从顶上放元素 也先从顶上出元素

调用完函数后 从顶上开始结束函数 最后来到main函数这里

调用堆栈很好的反映了函数是如何一步一步的调用的

实例3:计算阶乘1!+2!+3!+...+n!

此代码有错 当输入n = 3时 结果本应该时 1!+2!+3! =9 但程序结果却是15

通过F10一步一步调试 原因如下:

发现当计算2!的时候 ret 的变成了2 也就是说ret的累乘效果没有取消, ret == 2的结果一直在往后的循环中累计使用,导致ret一直在变大 结果也跟着变大。

想要计算的是1!+2!+...+n!

但是此代码算成了1!+1!2!+1!2!3!+...+1!2!...n!

计算阶乘的原理: 输出1-n的数字 然后乘到一个变量(ret)上去 也就是说 影响结果因素只有输入的n的大小,变量ret只是用来接收乘积结果的。

错误的原因就在这里:ret变量的值没有重复初始化为1

通过一步步调试 很快就找到了错误的原因

此代码还有可以进行优化 :利用 ret 的累乘效果 原理:n!=(n-1)!*n

在每一次for循环结束前 及时把ret加到sum上去

实例4:模拟字符串拷贝函数strcpy()

strcpy函数功能 拷贝source(源头)字符串到 Destination(目的地) 拷贝的字符包括'\0'

模拟strcpy函数 my_strcpy

原理:把要拷贝的数组传参之后 解引用对被覆盖的数组进行赋值 判断条件为*str != '\0'

最后再把'\0'字符拷贝

由于把'\0'字符也一并拷贝过去了 printf打印的时候 遇到\0停止打印 打印结果相同

此代码有四个地方可以优化

1.

while循环条件可以改成复合赋值符的形式

2.

给非被覆盖数组const修饰

原因:用const修饰 防止数组传参的时候不小心写反了 这时候 src就是被覆盖数组 程序就会报错 因为const修饰的常变量 无法被修改

3.

assert断言

防止dest和src传过来的时候是空指针 影响拷贝

4.

返回值

拷贝完成后,将dest的首元素地址返回

完整代码如下:

最后用相同的思路模拟求字符串长度的函数strlen()

相关文章
|
3月前
|
机器学习/深度学习 边缘计算 算法
虚拟同步发电机(VSG)惯量阻尼自适应控制仿真模型(simulink仿真实现)
虚拟同步发电机(VSG)惯量阻尼自适应控制仿真模型(simulink仿真实现)
349 0
|
数据可视化 JavaScript API
NGLView 安装与配置-交互式分子结构和轨迹查看
NGLView 安装与配置-交互式分子结构和轨迹查看
917 0
NGLView 安装与配置-交互式分子结构和轨迹查看
|
8月前
|
XML JSON 网络协议
利用HTTP POST协议实现简单的RPC协议:WireShark抓包分析
通过这种方式,我们可以使用HTTP POST实现简单的RPC协议,并使用WireShark进行抓包分析。这不仅可以帮助我们理解RPC协议的工作原理,也可以帮助我们调试和优化我们的代码。
419 30
|
消息中间件 分布式计算 负载均衡
ZooKeeper在哪些场景中被使用?
【6月更文挑战第21天】ZooKeeper在哪些场景中被使用?
550 38
|
关系型数据库 分布式数据库 PolarDB
PolarDB 开源部署体验评测
PolarDB 开源部署体验评测
336 3
|
Ubuntu Linux 虚拟化
CentOS7扩容踩坑记录(最后只有ubuntu成功)
这篇博客记录了一次尝试给CentOS根分区扩容的过程。作者在VMware中扩展了虚拟磁盘,但最终未能成功将新分区合并到现有卷组中,因为原有分区未创建物理卷(PV)和卷组(VG)。过程中遇到了多个问题,如分区文件正在使用中等。最终作者提醒读者在操作前务必先检查当前的分区和卷组状态。
258 4
CentOS7扩容踩坑记录(最后只有ubuntu成功)
|
开发者
ArkTS组件继承的高级用法
本文详细介绍了ArkTS中组件继承的高级用法,涵盖继承的概念、基本用法、多态、接口继承和抽象类的使用。通过具体示例,展示了如何在HarmonyOS应用开发中利用继承实现代码复用、功能扩展和模块化设计,提升开发效率和应用质量。
627 3
|
存储 人工智能 搜索推荐
揭秘LangChain+RAG如何重塑行业未来?保姆级实战演练,解锁大模型在各领域应用场景的神秘面纱!
【10月更文挑战第4天】随着AI技术的发展,大型语言模型在各行各业的应用愈发广泛,检索增强生成(RAG)技术成为推动企业智能化转型的关键。本文通过实战演练,展示了如何在LangChain框架内实施RAG技术,涵盖金融(智能风控与投资决策)、医疗(辅助诊断与病历分析)及教育(个性化学习推荐与智能答疑)三大领域。通过具体示例和部署方案,如整合金融数据、医疗信息以及学生学习资料,并利用RAG技术生成精准报告、诊断建议及个性化学习计划,为企业提供了切实可行的智能化解决方案。
555 5
|
缓存 安全 前端开发
Cloudflare
【7月更文挑战第13天】Cloudflare
766 5
|
存储 算法 编译器
【C++ 泛型编程 进阶篇】C++模板元编程深度解析:探索编译时计算的神奇之旅
【C++ 泛型编程 进阶篇】C++模板元编程深度解析:探索编译时计算的神奇之旅
1932 1