操作系统概念之-内存之堆与栈

2023-12-28 22:35:14

C++内存管理存在两个很重要的基础概念:堆(heap)和栈(stack)
而在数据结构中的堆栈,主要指的一段连续存取地址上的存取规则(算法),如:增加和删除项时采用后进先出(Last In First Out,LIFO),C++语言层面更关注“对象“因”“存储”区的不同,即“堆“或”栈“,而在内存管理(时效、范围)上的不同。
这里先了解内存空间

1.内存空间

内存是一个大的字节数组。
CPU只能从内存中加载指令,因此执行程序必须位于内存。内存提供字节数组,每个字节都有地址。内存单元(如一个字节内存单元)通过基本的load和store指令形成内存地址流(表达:指令(该内存单元是一个指令寄存器)或“数据”的改变(该内存单元是一个“数据”寄存器))

存储设备的的层次

2.进程与内存分配方式

在未被CPU执行之前,程序做不了任何事,执行的程序称为进程
进程创建时,可能就会分配(对象)内存(一般指“虚拟内存”,不是“物理内存”).
当进程终止时,资源会回收,包括分配的内存(可能是某实例化对象的地址)
单线程进程有一个计数器,指定了下一个(应该是顺序的)所要执行的指令
,直到进程结束。
在这里插入图片描述
(每一个进程都有自己的虚拟内存空间 如上图,其来源:https://zhuanlan.zhihu.com/p/56929325?utm_id=0),应该是作者从《深入理解计算机系统》3rd-2016上总结而来,本人不太懂,但觉得对理解程序代码被读入内存的状态很有用,特别是理解C++/C的内存管理机制。感谢作者的二次创作,有能力的也可以直接阅读《深入理解计算机系统》(3RD-CN)可下载电子版(https://download.csdn.net/download/www_djh/88669234?spm=1001.2014.3001.5503))
从上面这张图中**“进程虚拟存储器”,表达了C++/C语言对堆(heap)、栈(stack)两块不同内存区**的分配方式和回收方式,具体可看:《C++ Primer Plus》(6TH-CN)

相关概念:
(1)内存分配的增长方式:
堆:堆的地址增长方式是从低到高的,一般采用LIFO,比如C++的vector容器中push与pop两个方法
栈:栈的地址增长方式是从高到低的,一般采用FIFO
(2)如果按照整个内存区分配的先后,由先到后,把上图倒过来是不是更好理解些。
(3)栈:
C++,在函数中声明的任何局部变量(非静态)都是在栈中分配的(编译期间完成)。并且函数的参数,以及返回值也是依赖于栈。 如:数组初始化,则每个数组元素(连续)分配的栈地址,下标越大的地址越高。因数组元素地址是连续的,所以,可通过下标直接计算偏移。

int main()
{
    int a = 1;
    int b = 2;
    printf("%d,%d",a, a=a+b );
}

说明:上面这段代码的输出结果:3,3。解释:因为函数参数的入栈顺序是从右到左的。另:它也揭露了一个事实,那就是函数参数(应该是指“a=a+b”)是存入栈中的,如果参数是表达式,那么一定要先计算出表达式的值,然后再入栈。(引用:知乎:https://zhuanlan.zhihu.com/p/56929325?utm_id=0)
(4)堆:
所谓“堆”,即动态存储区,与栈不同,堆是在程序运行时被分配的。C语言中的malloc,C++中的new完成的都是堆上的操作。堆不会自动释放所以需要free和delete。
1)malloc和new的不同:首先:malloc是函数,而new是关键字。然后new作为C++中动态对象创建的基石,除了完成堆空间的分配操作以外还要完成一些初始化操作,及new的过程中会调用对象的构造函数去初始化,而malloc不会。最后要明确的是malloc分配的内存只能用free来释放,而new分配的地址只能用delete来释放,如果new分配的是数组,则需要delete[ ]来释放,否则会出现未定义行为。

2)无论是malloc还是new返回的都是一个指针,即堆地址。堆与栈不同:堆不是顺序分配的,而是离散分配的,它的空闲内存可能不是连续的,而是断断续续的(由:堆内存的首地址及其偏移量(分配空间的大小)确定),通常通过链表来连接每个空闲存储区。

纯粹学习笔记,学习的资料在文中已标注

文章来源:https://blog.csdn.net/www_djh/article/details/135223690
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。