存储类别、链接和内存管理(三)--面试官有问你堆与栈吗?

简介: 介绍存储类别、内存管理。

1、堆

在内存的全局存储空间中,用于程序动态分配和释放的内存块称为自由存储空间,通常也称之为堆。

在C程序中,我们用malloc和free函数来从堆中动态地分配和释放内存

#include "stdio.h"
2 #include "stdlib.h"/* malloc和free函数的原型 */
4 int main(void)5{
6
int *p;
p =(int*)malloc(sizeof(int));*p =123456;
9 printf("the num is : *d\n" *p); 
free(p);
11  return 0; 
12}
the num is :123456
请按任意键继续.

这里需要提醒基础不好的同学,

printf("the num is : *d\n",*p);

第九行,*p打印出p的值对应的存储单元的数据;

如果是p,则打印p的值(是个地址,指针变量存放的值是个地址)。

int main(void)5 {
6 int *p; 
7 p = (int*)malloc(sizeof(int));  
8 *p =123456; 
9 printf("the num is :号d\n  p); 
10  free(p);  
11  return 0; 
12} 
the num is :4656960请按任意键继续

这个值每次打印都不一样。

640.png

2.栈

   栈是用来存放局部变量、函数的参数以及调用函数和被调用函数的联系的内存池。它是一种先进后出的压入弹出式的数据结构。栈内存由编译器在需要的时候自动分配,在不需要的时候自动销毁的变量。

3.free函数的重要性

  静态内存的数量在编译时是固定的,在程序运行期间也不会改变。自动变量使用的内存数量在程序执行期间自动增加或减少。但是动态分配的内存数量只会增加,除非用 free()进行释放。内存不进行释放,会造成内存泄漏,甚至可能会导致系统崩溃。

   free函数的用处在于实时地执行回收内存的操作,如果程序很简单,程序结束之前也不会使用过多的内存,不会降低系统的性能,那么也可以不用写free函数去释放内存。程序结束之后,操作系统会完成释放功能。

   但是在开发大型程序时如果不写free函数去释放内存,后果是很严重的。如果程序要重复10000次10MB的内存分配,如果每次用完都释放,那程序只需要10MB就行了,但是如果不适用free函数释放,那么程序就要使用100G内存。这其中包括绝大部分的虚拟内存,而由于虚拟内存的操作需要读写磁盘,这会极大地影响系统性能,系统可能因此崩溃。

总结

存储类别和动态内存分配有何联系?我们来看一个理想化模型。可以认为程序把它可用的内存分为3部分:一部分供具有外部链接、内部链接和无链接的静态变量(static)使用;一部分供自动变量使用;一部分供动态内存分配。

静态存储类别所用的内存数量在编译时确定,只要程序还在运行,就可访问储存在该部分的数据。该类别的变量在程序开始执行时被创建,在程序结束时被销毁。

然而,自动存储类别的变量在程序进入变量定义所在块时存在,在程序离开块时消失。因此,随着程序调用函数和函数结束,自动变量所用的内存数量也相应地增加和减少。这部分的内存通常作为栈来处理,这意味着新创建的变量按顺序加入内存,然后以相反的顺序销毁。

动态分配的内存在调用 malloc()或相关函数时存在,在调用 free()后释放。这部分的内存由程序员管理,而不是一套规则。所以内存块可以在一个函数中创建,在另一个函数中销毁。正是因为这样,这部分的内存用于动态内存分配会支离破碎。也就是说,未使用的内存块分散在已使用的内存块之间。另外,使用动态内存通常比使用栈内存慢。总而言之,程序把静态对象、自动对象和动态分配的对象储存在不同的区域。

号主:一枚机械专业本科生,经历了转行,从外包逆袭到芯片原厂的Linux驱动开发工程师,深入操作系统的世界,贯彻终身学习、终身成长的理念。平时喜欢折腾,寒冬之下,抱团取暖,期待你来一起探讨技术、搞自媒体副业,程序员接单和投资理财。【对了,不定期送闲置开发板、书籍、键盘等等】。

如果你想了解我的转行经验,欢迎找我交流~gongzhong号【哆哆jarvis】

一起不断探索自我、走出迷茫、找到热爱,希望和你成为朋友,一起成长~

相关文章
|
3天前
|
存储 监控 Java
深入剖析堆和栈的区别及其在内存管理中的影响
深入剖析堆和栈的区别及其在内存管理中的影响
|
10天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
22 2
|
13天前
|
存储
数据在内存中的存储(了解数据在内存中的存储规则,看这一篇就够了!)
数据在内存中的存储(了解数据在内存中的存储规则,看这一篇就够了!)
|
3天前
|
存储 JavaScript 前端开发
javascript的栈内存 VS 堆内存(浅拷贝 VS 深拷贝)
javascript的栈内存 VS 堆内存(浅拷贝 VS 深拷贝)
7 0
|
3天前
|
存储
|
3天前
|
存储 监控 Java
深入剖析堆和栈的区别及其在内存管理中的影响
深入剖析堆和栈的区别及其在内存管理中的影响
|
8天前
|
程序员 编译器 C++
C++内存分区模型(代码区、全局区、栈区、堆区)
C++内存分区模型(代码区、全局区、栈区、堆区)
9 0
|
9天前
|
存储 监控 算法
Java中的内存管理:从堆到栈的深入解析
Java中的内存管理:从堆到栈的深入解析
|
9天前
|
存储 C语言
【C语言进阶篇】整数在内存的存储——原码、反码、补码
【C语言进阶篇】整数在内存的存储——原码、反码、补码