卡码笔记
首页
计算机基础
C++
Java
面经
笔记广场 (opens new window)
代码随想录 (opens new window)
首页
计算机基础
C++
Java
面经
笔记广场 (opens new window)
代码随想录 (opens new window)
  • 基础与语法

  • 面向对象

  • STL 与容器

  • 内存管理

    • C++内存分区,堆和栈的区别
      • 简要回答
      • 详细回答
      • 代码示例
      • 知识拓展
    • new和melloc的区别是什么?
    • free和delete区别的是什么?
    • placement new的作用
    • 什么是内存泄漏?什么是野指针?什么是内存越界?如何避免?
    • 内存碎片与内存溢出
    • 如何避免内存碎片
  • C++11 与现代 C++

  • 智能指针

  • 并发与 I/O

# C++内存分区,堆和栈的区别

# 简要回答

c++的内存分区从低地址到高地址分别是:

代码段:存储程序的机器指令(函数体),只读,可能共享。

数据段:存放未初始化的静态常量,全局变量

BSS段:未初始化的静态常量,全局变量以及初始化为0的全局变量

栈:适合存储生命周期较短,大小固定的对象,编译器自动分配释放,优点是高效且安全,但空间小

堆:适合存储生命周期较长,大小动态变化的对象,动态分配内存区域,由程序员手动管理,使用时要谨慎管理内存,空间大,但管理复杂,容易内存泄漏

# 详细回答

  1. 栈区:由编译器在需要的时候分配,在不需要的时候自动清除的变量存储区,里面的变量通常是局部变量、函数参数等

  2. 堆区:由new分配的内存块,他们的释放编译器不去管,由程序去控制,一般一个new就要对应一个delete

  3. 自由存储区:就是那些由malloc等分配的内存块,它和堆是十分相似的,不过它是用free来结束自己的生命的

  4. 全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区

  5. 常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改

  6. 代码区:存放在机器指令,只读,很安全

  • 区分堆和栈

    1.管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak

    2.空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。

但是对于栈来讲,一般都是有一定的空间大小的。

3.碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。

对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出。

4.生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

5.分配方式:堆都是动态分配的,没有静态分配的堆,栈有2种分配方式:静态分配和动态分配。

静态分配是编译器完成的,比如局部变量的分配, 动态分配由 malloc 函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

6.分配效率:堆的效率比栈要低得多。栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。

堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。

# 代码示例

#include <iostream>
using namespace std;

int global_var = 10;         // 全局区
const int const_global = 20; // 常量区

void demo() {
    int local_var = 30;      // 栈区
    int* heap_var = new int(40); // 堆区

    cout << "local_var addr: " << &local_var << endl;
    cout << "heap_var addr:  " << heap_var << endl;
    cout << "global_var addr: " << &global_var << endl;
    cout << "const_global addr: " << &const_global << endl;

    delete heap_var; // 不释放就内存泄漏
}

int main() {
    demo();
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 知识拓展

  • 内存图解 image

  • 栈和堆的线程安全

栈是线程私有的:每个线程有自己的栈,天然线程安全。

堆是线程共享的:多个线程可能访问同一内存,因此要加锁或用原子操作保护。

  • 面试官可能会追问的问题

平时你在项目中怎么管理内存?

答:作答时可以往使用智能指针、RAII原则、内存池等方案,针对自己具体项目进行解释。

Last Updated: 3/10/2026, 6:08:48 PM

← push_back()和emplace_back()的区别 new和melloc的区别是什么? →

评论

验证登录状态...

侧边栏
夜间
卡码简历
代码随想录
卡码投递表🔥
2026群
添加客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记
鼓励/支持/赞赏Carl
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪