数据结构(Day13)
一、学习内容
-
内存空间划分
-
1、一个进程启动后,计算机会给该进程分配4G的虚拟内存
2、其中0G-3G是用户空间【程序员写代码操作部分】【应用层】
3、3G-4G是内核空间【与底层驱动有关】
4、所有进程共享3G-4G的内核空间,每个进程独立拥有0G-3G的用户空间
5、内存分区的目的是:专人专项、提高效率
-
栈区特点
-
运行时自动分配和回收: 栈是自动管理的,程序员不需要手工干预,使用起来方便简单。
-
反复使用: 栈内存在程序中其实就是那一块空间,程序反复使用这一块空间。
-
脏内存: 栈内存由于反复使用,每次使用后程序不会去清理,因此分配到时如果没有初始化会保留原来的值。
-
临时性: 函数不能返回栈变量的指针,因为这个空间是临时的。
-
栈会溢出: 因为操作系统事先给定了栈的大小,如果在函数中无穷尽的分配栈内存总会消耗完。
-
栈空间是向下增长的
-
-
堆区特点
-
大块内存: 堆内存管理是总量很大的操作系统内存块,各进程可以按需申请使用,使用完释放。
-
程序手动申请和释放: 手工意思是需要写代码去申请malloc()和释放free()。
-
脏内存: 堆内存也是反复使用的,而且使用者用完释放前不会清除,因此也是脏的。
-
临时性: 堆内存只在申请malloc()和释放free()之间属于这个进程,可以访问。在释放free()之后不能再访问,否则会有不可预料的后果。
-
不可直接操作: 需要通过指针操作。
-
堆空间是向上增长的
-
-
堆和栈的区别
-
管理分配效率不同。栈编译器自动管理,无需程序员手工控制;而堆空间的申请释放工作由程序员控制,容易产生内存泄漏。堆的效率比栈要低
-
空间大小不同。栈是向低地址扩展的数据结构,是一块连续的内存区域。堆是向高地址扩展的数据结构,是不连续的内存区域。
-
是否产生碎片。对于堆来讲,频繁的malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。对于栈来讲,则不会存在这个问题。
-
增长方向不同。堆的增长方向是向上的,即向着内存地址增加的方向;栈的增长方向是向下的,即向着内存地址减小的方向。
-
-
-
-
动态内存分配和回收(申请和释放)
-
malloc函数
-
功能:在堆区开辟指定字节的空间
-
头文件:#include <stdlib.h>
-
原型:void *malloc(size_t size);
-
分析:返回值是void *【通用型指针】——可以转换成任意类型的指针
-
参数是size_t size 【数据类型 size_t 64位是long int——%ld 32位是int——%d】 【size表示的是索要开辟的空间的大小】
-
-
-
free函数
-
功能:手动释放堆区空间
-
头文件:#include <stdlib.h>
-
原型:void free(void *ptr); //无返回值函数 参数是void *ptr 【通用型指针,传参直接传指针名即可】
-
-
常见的内存错误
-
野指针
-
原因
-
指向动态分配内存的指针在释放后,没有NULL
-
指向被删除的对象或无效对象的指针
-
接收了函数返回的局部变量的指针
-
-
解决方法
-
malloc() free()后及时NULL
-
及时更新指针
-
编码时明确变量的作用域,不要接收返回的局部变量的指针
-
-
-
内存越界
-
原因
-
访问到野指针指向的区域,越界访问
-
数组下标越界访问
-
向缓冲区写入超过其容量的数据【strcpy、strcat的例子】
-
-
解决方法
-
使用数组时确保下标的范围,使用循环计数或条件判断控制范围
-
使用指针时,进行if(NULL==p)的检查
-
使用strncat 和 strncpy可以确保不会溢出目标缓冲区 strcpy(dest , src); strncpy(dest , src , strlen(dest))
-
-
-
内存泄漏
-
如果没有适时释放被动态分配的内存,会导致内存泄露问题。未释放的内存一直占用系统资源,使得系统变慢并最终导致崩溃。
-
原因
-
丢失了分配的内存的首地址,导致无法释放
-
每循环一次,泄露一次内存
-
非法访问常量区
-
-
解决方法
-
及时使用free()释放不再使用的内存
-
合理设计数据结构和算法,避免内存无线增长
-
设置合理的变量【作用域】,减少内存占用
-
-
-
-
-
-
脑图

二、作业
-
p 和 "hello,world"存储在内存哪个区域?( ) (鲁科安全)
int main()
{
char *p = "hello,world";
return 0;
}
解析:
字符串 "hello,world" 是一个字符串字面量,在编译时会存储在程序的 常量区(或者叫做只读数据段) 中。该区域通常是只读的,不能被修改。
变量 p 是一个指针变量,它指向字符串 "hello,world"。因为 p 是在 main() 函数中定义的局部变量,所以它存储在 栈区 中。
解答:
*p在栈区 "hello,world"在静态区中的.ro段
-
一个由C/C++编译的程序,会将占用的内存分为几个部分:堆、栈、代码段、数据段、BSS段。请问以下程序中的变量a、b、c、d,分别被存在内存的哪个部分?(泰华智慧)
int a = 0;
char *b;
int main()
{
int c;
static char d = 'a';
b = malloc(10);
*b = d;
return 0;
}
解析:
变量
a:变量
a是一个全局变量并且初始化为0。存储区域:数据段(已初始化的全局变量存储在数据段)。
变量
b:变量
b是一个全局指针变量,但它没有初始化。存储区域:BSS 段(未初始化的全局变量和静态变量存储在 BSS 段中)。
变量
c:变量
c是在main函数内部定义的局部变量。存储区域:栈区(局部变量存储在栈区)。
变量
d:变量
d是一个静态局部变量并初始化为'a'。存储区域:数据段(静态局部变量也存储在数据段中,因为它已初始化)。
解答:
变量a在数据段、b在bss段、c在栈区、d在数据段
-
如下代码:变量g_iA,g_iB,g_iC,iD,iE, iF, piG,iH 分别在内存中的什么区( ) (H3C)
int g_iA = 1;
int g_iB;
static int g_iC = 1;
void func1(){
static int iD=2;
iD++;
int iE=2;
iE++;
}
void func2(){
int iF=3;
int *piG = (int*) malloc(4);
}
int main(){
int iH = 100;
}
解析:
g_iA:这是一个已初始化的全局变量。
存储区域:data段(已初始化的全局变量存储在数据段中)。
g_iB:这是一个未初始化的全局变量。
存储区域:BSS 段(未初始化的全局变量存储在 BSS 段中)。
g_iC:这是一个已初始化的静态全局变量。
存储区域:data段(已初始化的静态全局变量也存储在数据段中)。
iD:这是在
func1函数中定义的已初始化的静态局部变量。存储区域:data段(静态局部变量存储在数据段中,无论函数是否被调用)。
iE:这是在
func1函数中定义的局部变量。存储区域:栈区(局部变量存储在栈中,每次函数调用时都会分配新的内存)。
iF:这是在
func2函数中定义的局部变量。存储区域:栈区(局部变量存储在栈中)。
piG:这是在
func2函数中定义的指针,malloc(4)动态分配了 4 字节的内存,piG指向这块内存。存储区域:栈区(指针
piG本身) 和 堆区(malloc(4)动态分配的内存)。
iH:这是在
main函数中定义的局部变量。存储区域:栈区(局部变量存储在栈中)
解答:
g_iA在静态区中的.data段、g_iB在静态区的.bss段、g_iC在静态区的.data段、iD在静态区的.data段、iE在栈区、iF在栈区、piG在栈区、iH在栈区
-
有关内存的思考题 (山东山大电力技术有限公司,登虹科技,昆腾微电子)
void GetMemory(char *p)
{
p =(char *)malloc(100);
}
void Test(void)
{
char *str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
请问运行 Test 函数会有什么样的结果?
char * GetMemory(void)
{
char pl[] = "hello world"; //char *p = "hello world"
return p1;
}
Void Test(void)
{
char *str=NULL;
str = GetMemory();
printf(str);
}
请问运行 Test 函数会有什么样的结果?
void GetMemory(char **p,int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello world");
printf(str);
}
请问运行 Test 函数会有什么样的结果?
void Test (void)
{
char *str = (char *)malloc(100);
strcpy(str,"hello");
free(str);
if(str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
请问运行 Test 函数会有什么样的结果?
解析:
1、第一段
在
GetMemory函数中,参数p是一个局部指针变量,当malloc(100)动态分配内存时,只是将地址赋值给局部的p,而不会影响调用者Test中的str。换句话说,str仍然是NULL。随后在Test中调用strcpy(str, "hello world")时,会试图向NULL指针中写入数据,这会导致 段错误(Segmentation Fault)。2、第二段
GetMemory函数中,p1[]是一个局部数组,存储在栈区。当GetMemory函数返回时,栈帧将被释放,局部变量p1将变为无效。虽然GetMemory返回p1的地址,但是这个地址指向已经被释放的栈空间,尝试访问该地址的内容是未定义行为。3、第三段
在GetMemory中,传递的是str的地址(&str),因此函数可以正确地分配内存并将其赋值给str。随后strcpy(str, "hello world")将字符串拷贝到分配的内存中,并调用printf(str)输出字符串。
4、第四段malloc(100)分配了 100 字节的内存,随后strcpy(str, "hello")将字符串"hello"拷贝到这块内存。free(str)释放了str指向的内存。虽然在C中,调用free并不会自动将指针置为NULL,但在if (str != NULL)语句中,str依然保持其原来的值(它指向已释放的内存)。由于内存已经被释放,再次尝试strcpy(str, "world")将会向一块已经释放的内存写入数据,这是未定义行为。
解答:
第一段:段错误
第二段:段错误
第三段:"hello,world"
第四段:程序崩溃
-
堆和栈的区别是什么? (矩阵软件)
解答:
管理分配效率不同。栈编译器自动管理,无需程序员手工控制;而堆空间的申请释放工作由程序员控制,容易产生内存泄漏。堆的效率比栈要低
空间大小不同。栈是向低地址扩展的数据结构,是一块连续的内存区域。堆是向高地址扩展的数据结构,是不连续的内存区域。
是否产生碎片。对于堆来讲,频繁的malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。对于栈来讲,则不会存在这个问题。
增长方向不同。堆的增长方向是向上的,即向着内存地址增加的方向;栈的增长方向是向下的,即向着内存地址减小的方向。
-
什么是内存泄漏?面对内存泄漏和指针越界,你有哪些方法?(山大华天,智洋创新)
解答:
1、如果没有适时释放被动态分配的内存,会导致内存泄露问题。未释放的内存一直占用系统资源,使得系统变慢并最终导致崩溃。
2、
及时使用free()释放不再使用的内存
合理设计数据结构和算法,避免内存无线增长
设置合理的变量【作用域】,减少内存占用
三、总结
1. 学习内容概述
内存管理
通过对堆和栈的详细讨论,讲解了内存分配的过程。栈用于自动变量分配,堆用于动态内存分配.
动态内存分配与回收
使用 `malloc`、`free` 等函数来分配和释放内存。
重点包括 `malloc()` 函数的使用方法、返回指针的类型、以及如何合理使用 `free()` 函数来释放动态内存,避免内存泄漏。
内存优化
结合了动态分配的方式和内存碎片问题,指出合理的内存使用和优化内存分配策略的重要性。
高性能与低性能
介绍了高效的内存使用方法以及可能导致低效的内存管理方式,提醒避免内存碎片和滥用动态内存分配。
2. 学习难点
指针的正确使用
在 `malloc()` 函数中分配内存时,返回的指针类型需要转换为适当的类型。初学者容易犯错的地方在于未进行正确的类型转换,或者忘记 `free()` 导致内存泄漏。
内存泄漏
在动态内存分配中,忘记释放不再使用的内存会导致内存泄漏问题,尤其是在大型程序中,内存泄漏将对程序性能产生严重影响。
内存碎片化
不合理的内存分配会导致内存的碎片化问题,影响程序的执行效率,理解并优化内存分配策略具有一定难度。
3. 主要事项
内存分配时需要注意内存对齐
在某些平台上,内存分配需要根据特定的对齐要求进行,否则可能导致性能问题或程序崩溃。
动态内存分配的错误处理
如果 `malloc()` 返回 `NULL`,应及时处理以避免空指针引用。
合理使用 `free()` 释放内存
避免在释放后继续使用已释放的内存,使用悬空指针可能会导致未定义行为。
优化程序的内存使用
避免频繁的内存分配和释放操作,减少内存碎片问题。
4. 未来学习的重点
深度理解内存分配的机制
更深入地理解堆栈的使用区别,尤其在不同平台上的表现差异。
内存调试工具的使用
掌握调试工具(如 `valgrind`)用于检测内存泄漏和内存管理错误,帮助排查问题。
进一步研究复杂数据结构中的内存管理
学习如何在链表、树、图等复杂数据结构中进行有效的动态内存分配和释放。
多线程程序中的内存管理
在并发编程中,了解内存管理的挑战,尤其是当多个线程共享内存时的同步问题。
相关文章:
数据结构(Day13)
一、学习内容 内存空间划分 1、一个进程启动后,计算机会给该进程分配4G的虚拟内存 2、其中0G-3G是用户空间【程序员写代码操作部分】【应用层】 3、3G-4G是内核空间【与底层驱动有关】 4、所有进程共享3G-4G的内核空间,每个进程独立拥有0G-3G的用户空间 …...
链表的快速排序(C/C++实现)
一、前言 大家在做需要排名的项目的时候,需要把各种数据从高到低排序。如果用的快速排序的话,处理数组是十分简单的。因为数组的存储空间的连续的,可以通过下标就可以简单的实现。但如果是链表的话,内存地址是随机分配的…...
css总结(记录一下...)
文字 语法说明word-wrapword-wrap:normal| break-word normal:使用浏览器默认的换行 break-word:允许在单词内换行 text-overflow clip:修剪文本 ellipsis:显示省略符号来代表被修剪的文本 text-shadow可向文本应用的阴影。能够规定水平阴影、垂直阴影、模糊距离,以…...
SpringBoot 处理 @KafkaListener 消息
消息监听容器 1、KafkaMessageListenerContainer 由spring提供用于监听以及拉取消息,并将这些消息按指定格式转换后交给由KafkaListener注解的方法处理,相当于一个消费者; 看看其整体代码结构: 可以发现其入口方法为doStart(),…...
Spring Boot-API版本控制问题
在现代软件开发中,API(应用程序接口)版本控制是一项至关重要的技术。随着应用的不断迭代,API 的改动不可避免,如何在引入新版本的同时保证向后兼容,避免对现有用户的影响,是每个开发者需要考虑的…...
Git 提取和拉取的区别在哪
1. 提取(Fetch) 操作说明:Fetch 操作会从远程仓库下载最新的提交、分支信息等,但不会将这些更改合并到你当前的分支中。它只是将远程仓库的更新信息存储在本地,并不会自动修改你当前的工作区。 使用场景: …...
【数据结构与算法 | 每日一题 | 力扣篇】力扣2390, 2848
1. 力扣2390:从字符串中删除星号 1.1 题目: 给你一个包含若干星号 * 的字符串 s 。 在一步操作中,你可以: 选中 s 中的一个星号。移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。 返回移除 所有 星号之…...
破解信息架构实施的密码:常见挑战与最佳解决方案全指南
信息架构的成功实施是企业数字化转型的关键步骤,但在实际操作中,企业往往会遇到各种复杂的挑战。这些挑战包括 技术整合的难度、数据管理的复杂性、合规性要求的变化 以及 资源限制 等。《信息架构:商业智能&分析与元数据管理参考模型》为…...
CodeChef Starters 151 (Div.2) A~D
codechef是真敢给分,上把刚注册,这把就div2了,再加上一周没打过还是有点不适应的,好在最后还是能够顺利上分 今天的封面是P3R的设置菜单 我抠出来做我自己的游戏主页了( A - Convert string 题意 在01串里面可以翻转…...
Redis学习——数据不一致怎么办?更新缓存失败了又怎么办?
文章目录 引言正文读写缓存的数据一致性只读缓存的数据一致性删除和修改数据不一致问题操作执行失败导致数据不一致解决办法 多线程访问导致数据不一致问题总结 总结参考信息 引言 最近面试快手的时候被问到了缓存不一致怎么解决?一开始还是很懵的,因为…...
跨境电商代购新纪元:一键解锁全球好物,系统流程全揭秘
添加图片注释,不超过 140 字(可选) 在全球化日益加深的今天,跨境电商代购成为了连接消费者与世界各地优质商品的桥梁。本文将在CSDN平台上,深入剖析跨境电商代购系统的功能流程,带您一窥其背后的技术奥秘与…...
Mac 上终端使用 MySql 记录
文章目录 下载安装终端进入 MySql常用操作查看数据库选择一个数据库查看当前选择的数据库Navcat 打开提示报错参考文章 下载安装 先下载社区版的 MySql 安装的过程需要设置 root 的密码,这个是要进入数据库所设定的,所以要记住 终端进入 MySql 首先输…...
461. 汉明距离
一:题目: 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y,计算并返回它们之间的汉明距离。 示例 1: 输入:x 1, y 4 输出:2 解释: 1 (0 0…...
开发指南061-nexus权限管理
平台后台服务的核心是组件,管理组件的软件有: Apache的Archiva、JFrog的Artifactory、Sonatype的Nexus。 本平台选择nexus。nexus的权限模型是用户-角色-权限体系:通过组合权限定义角色,通过给用户赋角色来赋权限。有关nexus的权…...
Qt 弹出菜单右键菜单 QMenu 设置不同颜色的子项
概述 在Qt中,可以使用样式表(StyleSheet)来自定义 QMenu 的外观,包括其子项(如菜单项QAction)的颜色。但是,这通常可以设置 QMenu 的整体样式,而不能单独设置某个子项的颜色。不过&…...
Git换行符自动转换参数core.autocrlf的用法
core.autocrlf 是 Git 中用于控制换行符自动转换的配置选项。它有以下几个可能的值: 1. true 作用:在 checkin 时将 CRLF 转换为 LF,在 checkout 时将 LF 转换为 CRLF。适用场景:适用于 Windows 用户,希望在本地文件…...
C语言的结构体类型
在我们使用C语言进行编写代码时,常常会使用已经给定的类型来创建变量,比如int型,char型,double型等,而当我们想创建一些较为复杂的东西时,单单用一个类型变量是没办法做到的,比如我们想创建一个…...
illustrator 收集字体插件VBscript
这是早些年从俄罗斯网站上看到的一个收集字体插件,语言是用VBscript写的,能用,但个别字体不能收集完成,现在Adobe也在illustrator中加入了收集字体打包功能,所以这个也很少用啦。 使用方法: 下好插件,或把下面的代码存入到本地侯后缀名改为.vbs,然后把.ai文件往.vbs文…...
【LLM多模态】文生视频评测基准VBench
note VBench的16个维度自动化评估指标代码实践(待完成)16个维度的prompt举例人类偏好标注:计算VBench评估结果与人类偏好之间的相关性、用于DPO微调 文章目录 note一、相关背景二、VBench评测基准概述:论文如何解决这个问题&…...
通过覆写 url_for 将 flask 应用部署到子目录下
0. 缘起 最近用 flask 写了一个 web 应用,需要部署到服务器上。而服务器主域名已经被使用了,只能给主域名加个子目录进行部署,比如主域名 example.org ,我需要在 example.org/flask 下部署。这时 flask 应用里的内部连接们就出现…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用
阻止除自定义标签之外的所有标签 先输入一些标签测试,说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时(如通过点击或键盘导航&…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...
Qwen系列之Qwen3解读:最强开源模型的细节拆解
文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...
