当前位置: 首页 > news >正文

C++面试——内存

一、简述堆和栈的区别

维度栈(Stack)堆(Heap)
生命周期随函数调用自动创建/销毁由程序员或垃圾回收器控制
分配速度极快(仅移动指针)慢(需查找空闲块、维护元数据)
空间大小较小(通常 MB 级)较大(受系统内存限制)
连续性连续内存,自上而下生长非连续,易产生碎片
典型用途局部变量、函数参数动态数组、对象、大内存
线程安全每个线程独立栈多线程共享,需同步
示例int a = 10;int *p = new int(10);

一句话:栈像自动售货机,随拿随走;堆像仓库,按需申请、手动归还。


二、简述C++的内存管理

C++ 的内存管理可简化为 “三区域、两手段、一原则”:

  1. 三区域

    • :函数帧自动创建/销毁,速度最快。
    • new/deletemalloc/free 手动申请/释放,空间大。
    • 静态/全局区:编译期确定,程序运行期间一直存在。
  2. 两手段

    • 手动管理:裸指针 + new/delete,高效但易漏/悬垂。
    • RAII + 智能指针std::unique_ptrstd::shared_ptr/weak_ptr 把资源生命周期绑定到对象生命周期,自动释放。
  3. 一原则

    资源即对象(RAII):获得资源即构造对象,离开作用域即释放资源——让编译器替你做 delete。

一句话

用智能指针和 RAII 包装资源,告别手动 delete,把内存管理交给作用域。


三、malloc和局部变量分配在堆还是栈?

分配方式所在区域生命周期示例
malloc / new堆(Heap)程序员手动 free/delete 或程序结束int* p = (int*)malloc(4);
局部变量栈(Stack)离开作用域自动销毁int x = 10;

一句话:malloc 永远落在堆;局部变量永远落在栈。


四、程序有哪些section,分别的作用?程序启动的过程?怎么判断数据分配在栈上还是堆上?

在这里插入图片描述
(1)、典型可执行文件(ELF)里的 section(段)

(按低→高地址排列,括号内为常见段名)

Section作用生命周期
.text机器指令(代码)只读,整个进程
.rodata只读常量(字符串、const 全局)同上
.data已初始化的全局/静态变量整个进程
.bss未初始化的全局/静态变量(默认 0)整个进程
heap运行时动态分配(malloc/new程序员控制
共享库映射区mmap 的 .so 文件、匿名映射按需加载
stack函数帧、局部变量、返回地址随函数进出
命令行参数 & 环境变量argc, argv, envp进程启动时由内核放进来
内核空间内核代码/数据(用户不可见)整个系统

(2)、程序启动的 9 步流程(Linux 为例)

  1. Shell fork → 创建子进程
  2. 内核 execve 装载 ELF
  3. 读 ELF header → 解析各个 section 偏移和长度
  4. 建立虚拟地址空间:
    • .text/.rodata/.data/.bss 映射进来
    • 为 heap 预留一段匿名映射(brk 起点)
    • 预留 stack 区域并设置 RSP
  5. 装载动态链接器 (ld-linux.so) → 映射到共享区
  6. 重定位 & 符号解析 → 把 .so.text/.data 填进共享区
  7. 初始化 .bss 为 0
  8. 运行 .init / __libc_start_main → 调全局对象构造函数
  9. 跳转到 main → 用户代码开始

(3)、如何判断数据在 栈 还是 堆?

场景所在区域判断技巧
int x = 5;作用域结束即销毁
int *p = new int(5);离开作用域后 *p 仍有效,需要 delete
static int x;全局区(.data/.bss)整个进程生命周期
`const char *s = “hello”;` 只读段(.rodata)地址位于低地址只读区域
malloc(…) 返回值gdb / pmap / cat /proc/$$/maps 可见匿名映射

最实用的运行时判断

pmap -x <pid>
  • 区间名 [stack] → 栈
  • 区间名 [heap] → 堆
  • 区间名 /lib/ld-linux.so → 共享区

一句话总结

代码在 .text,常量在 .rodata,全局/静态在 .data/.bss,动态在 heap,局部在 stack;启动时内核按 ELF 把段映射进虚拟地址空间,运行时看作用域和分配 API 即可区分栈与堆。



五、初始化为0的全局变量在bss还是data

初始化为 0(或全零)的全局变量 放在 .bss,而不是 .data

.data 只收“非零初始值”的全局/静态变量。)

int g1 = 0;          // .bss
int g2 = 42;         // .data
static int s1 = 0;   // .bss
static int s2 = 1;   // .data

一句话:

零初始化的全局/静态变量进 .bss,非零才进 .data



六、简述C++中内存对齐的使用场景

一句话:

“让数据在内存里按照 CPU 最喜欢的地址倍数排排坐,从而少一次访存、多一次 SIMD。”

1️⃣ 典型场景

场景原因关键词
结构体/类成员布局避免空洞、保证原子变量对齐#pragma pack, alignas
SSE/AVX 指令128/256/512 bit 必须 16/32/64 字节对齐alignas(16)
malloc/new 无法满足自定义对齐内存std::aligned_alloc, std::aligned_storage
共享内存/网络协议跨平台二进制兼容alignas(uint32_t)
原子操作std::atomic<T> 要求 T 自然对齐alignof(std::max_align_t)

2️⃣ 一行代码示例

struct alignas(32) Vec4 {float x, y, z, w;
};          // 起始地址一定是 32 的倍数,可直接 `_mm256_load_ps`

3️⃣ 口诀

“原子对齐保并发,SIMD 对齐保速度,协议对齐保兼容。”



http://www.lryc.cn/news/622308.html

相关文章:

  • docker重启或系统重启后harbor自动启动
  • MySQL快速恢复数据的N种方案完全教程
  • 口播数字人免费API调用方案
  • MC0439符号统计
  • 【学习笔记】NTP服务客户端配置
  • 9.对象介绍
  • 2025年COR SCI2区,泊位分配、岸桥分配与引航调度的集成规划,深度解析+性能实测
  • 下载及交叉编译zlib库,记录
  • 解决 MySQL 查询速度缓慢的问题
  • 力扣400:第N位数字
  • 【CUDA 编程思想】FusedQKVProj-分组量化矩阵乘法高效实现全流程解析
  • AutoSar AP平台中EM,CM,SM,PHM,LT等AP基础软件都有宿主进程吗
  • 【swift】SwiftUI动画卡顿全解:GeometryReader滥用检测与Canvas绘制替代方案
  • 超分——对比学习(Contrastive Learning)
  • mysql-DDLy语句案例
  • Unity 实现逼真书本翻页效果
  • 电子电气架构 --- 线束设计一些事宜
  • Linux软件编程-进程(2)及线程(1)
  • TDengine IDMP 高级功能(2. 事件模板)
  • 低资源语言翻译:数据增强与跨语言迁移学习策略
  • 第二十四天:虚函数与纯虚函数
  • 订单状态定时处理(Spring Task 定时任务)
  • OpenTelemetry WebSocket 监控终极方案:打通最后一公里
  • liteflow
  • kubernetes(4) 微服务
  • C#文件复制异常深度剖析:解决“未能找到文件“之谜
  • 大白话解析 Solidity 中的防重放参数
  • 大白话解析 Solidity 中的数据位置关键字 memory
  • [激光原理与应用-284]:理论 - 波动光学 - 无线电波,无线通信的频谱
  • 人工智能与社会治理:从工具到生态的范式重构