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

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.xdnf.cn/news/17884.html

相关文章:

  • Flutter 自定义组件开发指南
  • Spark03-RDD01-简介+常用的Transformation算子
  • 让数据可视化更简单:Embedding Atlas使用指南
  • initdata段使用方式
  • 第454题.四数相加II
  • Ant-Design AUpload如何显示缩略图;自定义哪些类型的数据可以使用img预览
  • 如何下载低版本的NVIDIA显卡驱动
  • Pytest项目_day17(随机测试数据)
  • 【LeetCode 热题 100】45. 跳跃游戏 II
  • 杭州网站建设:如何展示企业科研实力?
  • GitCode疑难问题诊疗
  • 状态流程框架(cola-component-statemachine)
  • 正点原子STM32H743配置 SDRAM
  • 序列晋升6:ElasticSearch深度解析,万字拆解
  • 【补充】数据库中有关系统编码和校验规则的简述
  • 非极大值抑制(NMS)详解:目标检测中的“去重神器”
  • 小兔鲜儿-小程序uni-app(二)
  • 【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
  • C语言基础00——基本补充(#define)
  • 非中文语音视频自动生成中文字幕的完整实现方案
  • 38 C++ STL模板库7-迭代器
  • 电子电气架构 --- 线束设计一些事宜
  • 商城开发中,有哪些需要关注的网络安全问题
  • 【大模型微调系列-02】 深度学习与大模型初识
  • tun/tap 转发性能优化
  • 如何通过ETLCloud做数据监听
  • 北京JAVA基础面试30天打卡10
  • Unity与OpenGL中的材质系统详解
  • 电子电气架构 --- 探索软件定义汽车(SDV)的技术革新
  • 力扣326:3的幂