『面试问答』:堆内存和栈内存有什么区别?
面试官: 请说一下,堆内存和栈内存有什么区别?
操作系统为了防止多进程运行时造成的内存地址冲突,引入了虚拟内存地址,为每个进程提供了一个独立的虚拟内存空间,使得进程以为自己独占全部内存资源。
对于进程虚拟内存的用户空间,从低往高,我们可以分六个不同的内存段,分别是代码段、数据段、BSS段、堆、文件映射段和栈。
在这六个内存段中,堆和栈是编程中经常用到的,也是最容易出错的地方。
栈用来存放程序中临时创建的局部变量,如函数的参数、内部变量等。每当一个函数被调用时,就会将参数压入进程调用栈中,调用结束后返回值也会被放回栈中。同时,每调用一次函数就会创建一个新的栈,所以在递归较深时容易导致栈溢出。栈内存的申请和释放由编译器自动完成,并且栈容量由系统预先定义,一般默认只有8M。栈从高地址向低地址增长。
栈内存为线程留出临时空间,每个线程都有一个固定大小的栈空间,而且栈空间存储的数据只能由当前线程访问,所以它是线程安全的。
堆内存是动态内存分配区域,用来存放动态分配的内存,堆内存由用户申请分配和释放,从低地址向高地址增长。在C和C++语言中使用malloc和new默认分配的内存就是堆内存。
堆内存的特点是大小不固定,可以动态扩容,空间由程序员动态分配,更加灵活。但是堆内存容易产生内存碎片,在分配和回收时需要对很多内存碎片进行整理,效率较低,所以我们一般都会通过内存分配器向堆区申请内存,比如通过glibc提供的接口malloc来动态申请内存。
此外,使用堆内存,还特别需要注意两个问题:
1、堆内存容易产生内存泄露,malloc出来的没有free,new出来的如果没有delete,都会产生内存泄露。
2、堆内存不像栈内存是线程独立的,它是线程不安全的,堆内存可以被一个进程内所有的线程访问,多线程操作时可能会产生问题。
分享软件开发岗位面试题及答案