【面试】面试常问之堆栈的区别


堆(heap)和栈(stack)在不同的场景下,代表的含义也不同,主要有两种: 在存储方面,堆与栈表示两种内存管理方式 在计算领域中,堆与栈表示两种常用的数据结构

1)堆栈在程序内存分区上的区别

进程为每个程序提供它自己的私有地址空间,每个这样的空间都有相同的通用结构,一个x86-64 Linux进程的地址空间的组织结构如下: 地址空间底部是保留给用户程序的,包括通常的代码、数据、堆和栈段。 代码段从地址0x400000开始 地址空间顶部保留给内核(操作系统常驻内存的部分),包含内核在代表进程执行指令时使用的代码、数据和栈。
    堆(heap):堆用来存放进程运行中被动态分配的内存段,需要程序员分配和释放。 栈(stack):在栈存放函数的参数值,返回值,局部变量等,由系统自动分配和释放。 区别: 管理方式: 对于栈来讲,是由编译器自动管理; 对于堆来说,释放工作由程序员控制,容易产生 memory leak。 空间大小: 一般来讲在 32 位系统下,堆内存可以达到接近 4G 的空间,从这个角度来看堆内存几乎是没有什么限制的。 但是对于栈来讲,一般都是有一定的空间大小的,例如,在 VC6 下面,默认的栈空间大小大约是 1M。 碎片问题: 对于堆来讲,频繁的new/delete 势必会造成内存空间的不连续,从而造成大量碎片,使程序效率降低; 对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,永远都不可能有一个内存块从栈中间弹出。 生长方向: 对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向; 对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。 分配方式: 堆都是动态分配的,没有静态分配的堆; 栈有 2 种分配方式:静态分配和动态分配。 静态分配是编译器完成的,比如局部变量的分配,动态分配由 alloca 函数进行分配。 但是栈的动态分配和堆是不同的,它的动态分配是由编译器进行释放,不需要我们手工实现。 分配效率: 栈是机器系统提供的数据结构,计算机会在底层分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高; 堆则是 C/C++函数库提供的,它的机制是很复杂的。 例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,然后进行返回。
关于C/C++中的堆栈以及内存管理更详细的介绍可移步。 但在Java中,栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。


2)堆栈在数据结构上的区别

    堆:一种常用的树形结构,是一种特殊的完全二叉树,当且仅当满足所有节点的值总是不大于或不小于其父节点的值的完全二叉树被称之为堆。 堆的这一特性称之为堆序性。 因此,在一个堆中,根节点是最大(或最小)节点。 如果根节点最小,称之为小顶堆(或小根堆),如果根节点最大,称之为大顶堆(或大根堆)。 堆的左右孩子没有大小的顺序。 堆常用来实现优先队列 栈:是一种运算受限的线性表,其限制是指只仅允许在表的一端进行插入和删除操作。 拥有“先进后出”的特性(First In Last Out),简称FILO。 允许操作这一端被称为栈顶(Top),相对地,把另一端称为栈底(Bottom)。 关于栈的两个最重要的操作是PUSH和POP。 PUSH操作在堆栈的顶部加入一个元素。 POP操作则相反,在堆栈顶部移去一个元素,并将堆栈的大小减1。 栈常用来实现递归


【部分内容参考自】

    《深入理解计算机系统》 堆与栈的区别:https://blog..net/K346K346/article/details/80849966/
经验分享 程序员 微信小程序 职场和发展