最近面试的时候遇到这个问题。这个问题考你计算机的基本功。
在 C/C++ 中,内存管理是控制程序如何分配和管理其资源的关键方面。C/C++ 程序中的内存通常分为不同的区域:堆栈和堆是最主要的动态和自动内存分配区域。
堆栈内存
- 定义:堆栈内存用于静态(自动)内存分配。它是存储函数参数、本地变量和返回地址的地方。当调用一个函数时,一个新的内存块(称为堆栈帧)会被添加到堆栈的顶部。当函数返回时,该内存会被自动释放。
- 分配:内存由系统自动管理——在变量超出作用域时自动分配和释放。无需人工干预。
- 生命周期:受限于函数或代码块的作用域。一旦函数退出,内存将被释放。
- 大小限制:堆栈的大小通常较小并由系统预定义,意味着大的分配可能导致堆栈溢出。
- 访问速度:由于其后进先出(LIFO)的结构,堆栈内存访问速度更快。由于内存是连续的且可预测的,它允许快速访问。
- 使用场景:局部变量、函数调用信息和固定大小的对象(数组、结构体)。
堆内存
- 定义:堆内存用于动态内存分配,程序员使用 C 中的 malloc()、calloc()、free() 和 C++ 中的 new、delete 手动分配和释放内存。
- 分配:内存在运行时分配,并且分配的生命周期由程序员手动控制。它可以持续存在,直到显式释放。
- 生命周期:堆分配的对象的生命周期不受作用域的限制。内存将一直被使用,直到被释放为止。
- 大小限制:堆通常比堆栈大,但取决于系统资源。不当处理可能导致内存泄漏(忘记释放分配的内存)或碎片化(内存使用效率低)。
- 访问速度:堆内存的访问速度比堆栈慢,因为分配是分散的,动态分配涉及更多的开销。
- 使用场景:如链表、树等大数据结构,或在运行时确定大小的对象。
堆与栈的主要区别
| 特征 | 堆栈 | 堆 |
|---|---|---|
| 内存大小 | 通常较小,预定义 | 通常较大,受系统资源限制 |
| 分配 | 自动,由编译器管理 | 手动,由程序员管理(使用 new、malloc 等) |
| 释放 | 自动(函数退出时) | 手动(使用 delete、free 等) |
| 生命周期 | 限于函数/代码块作用域 | 可以持续,直到显式释放 |
| 速度 | 较快(连续内存) | 较慢(分散内存,开销更大) |
| 风险 | 堆栈溢出(如果超出大小限制) | 内存泄漏和碎片化 |
堆栈分配示例
void function() {
int x = 10; // 分配在堆栈上
} // x 会自动释放
堆分配示例
void function() {
int* p = new int; // 分配在堆上
*p = 10;
delete p; // 必须手动释放
}
正确管理堆内存在 C/C++ 中非常重要,因为它可能导致与内存相关的错误,如内存泄漏或重复释放。理解堆和堆栈内存之间的差异有助于优化程序的性能和可靠性。
英文:The Memory Manager in C/C++ (Heap vs Stack)
面试经历
- 写了十几年代码, 谷歌/Google认为我还不够Senior
- Jane Street第一轮一小时面试体验卡(伦敦软件工程师)
- Meta/Facebook四次面试经历
- 三次冲击谷歌软件工程师: 我的面试起伏录 (谷歌面试是不是一生只有三次机会?)
- 记两次伦敦抖音面试经历(Tiktok)
- 我的面试谷哥GOOGLE伦敦SRE的经验和教训
- 记Facebook的第一轮技术面试(伦敦脸书)
- 记微软Principal SE的第一轮面试
- 我的AMAZON面试经历与经验之谈(亚麻伦敦面经)
- 离伦敦脸书最近的一次 - 记FACEBOOK伦敦终面经历
面试题
- 软件工程师面试: TCP/IP协议是什么?
- 软件工程师经典面试题: 当你在浏览器的地址栏敲入google.com并按回车后发生了什么?
- 谷歌面试题: 迷宫随机生成算法
- 软件工程师数据库面试技巧之 SQL中的第二名记录
- 软件工程师面试技巧之 动态规化 - 整数拆分
- 软件工程师面试技巧之 如何检查数独的有效性
- 去年 Google 的面试题 - 打印消息
- 软件工程师面试技巧之 使用哈希表降复杂度
- 微软面试题: 三角形的面积是多少?
- 英国 IT公司 电话面试的一些技巧 (程序员)
- C/C++ 中的内存管理器(堆与栈)
- C++的 map 当键(Key)不存在的时候会发生什么?
- 随机数独游戏的算法设计 (Sudoku)
- 经典二叉树的镜像的递归算法
- 谷歌的扔鸡蛋问题
- 面经: Python 的 List 和 Dictionary 有啥区别?
- 逻辑测试系列 - 一种只有4种语句的编程语言 - (1)
- 逻辑测试系列之二 - DECR
- 逻辑测试系列之三 - SUBT
面试技巧
面试其它
- 产品设计和系统设计面的区别(Product Design vs System Design)
- 45 分钟模拟面试(编程、系统设计)+职业发展建议
- 英国和美国IT公司面试的主要区别
- 拒了甲骨文(Oracle)的 Offer
C/C++编程
- 理解C++中的std::transform_reduce及示例
- 使用原子 TAS 指令实现自旋锁
- C++中检测编译时与运行时: if consteval 与 std::is_constant_evaluated()
- C++ 转发引用: 完美转发的关键
- 理解 C++ 中的 dynamic_cast: 安全的向下转型与向上转型
- C与C++: restrict关键字及其在编译器优化中的作用
- C++的左值/lvalue, 右值/rvalue和右值引用/rvalue references
- C++中的assert和static_assert的区别
- C++: auto_ptr智能指针被弃用
- C++中的consteval是什么? 它与const和constexpr有何不同?
- C++ 教程: 用std::move来移动所有权
- C++中的 const和constexpr 比较
- 简易教程: C++的智能指针
- C++ 编程练习题: 如何合并两个二叉树?
- C++ 编程练习题 - 找出第三大的数
- C++ 编程练习题 - 最多连续的 1
- C++ 编程练习题 - 左子树叶节点之和 (深度优先+广度优先+递归)
- C++ 编程练习题 - 最多水容器 (递归)
- C++的异步编程: std::future, std::async 和 std::promise
- C编程练习题: 翻转整数位
- C++编程练习题: 找出字符串的所有大小小组合
- C/C++ 中的内存管理器(堆与栈)
- C++编程练习题: 对两单向链表求和
上一篇: 软件工程师经典面试题: 当你在浏览器的地址栏敲入google.com并按回车后发生了什么?
下一篇: 软件工程师面试: TCP/IP协议是什么?
扫描二维码,分享本文到微信朋友圈
