ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

C++ 内存分区

C++ 内存分区

C++内存分区(虚拟地址空间,低地址 → 高地址)

注意:C++本身标准没有规定分区,我们说的是 Linux / Android 下进程虚拟内存布局。

顺序:低地址 → 高地址

代码段(.text)

只读常量段(.rodata)

数据段(.data)

BSS段(.bss)

堆(heap)

mmap映射区

栈(stack)

内核空间(用户态不可访问)

每一块存放内容、属性

.text 代码段

存放编译后的机器指令(函数代码),只读、可共享。

main、自定义函数、库函数指令都在这里。

.rodata 只读数据段(C++重点,很多教材单独拿出来)

只读:字符串字面量、const全局常量。

const char *p = "hello"; // "hello" 在rodata

不能修改,修改触发段错误;const局部变量不在这,在栈上!

.data 初始化数据段

初始化非0的全局变量、static静态变量,可读可写

int g_a = 100;

static int s_a = 10;

.bss 未初始化数据段

未初始化 / 初始值为0 的全局、static静态变量。

程序加载时操作系统统一清零;ELF文件中不占用bin体积。

int g_b;

static int s_b = 0;

✅ data + bss = 全局静态区

堆 heap

malloc / new 分配,向高地址增长

手动申请、手动释放;不释放造成内存泄漏。

大块内存malloc会走下面mmap

mmap内存映射区

动态库(.so)、文件映射、匿名映射;Android Camera HAL、vendor库都映射在这里。

栈 stack

局部变量、函数参数、返回地址、栈帧;向低地址增长

自动管理,函数调用结束自动回收;容量很小,容易栈溢出。

⚠️ 栈上的const int a=10只是变量只读,内存可写,只是编译器不让改,和rodata不是一回事。

最上方:内核空间,用户代码无法直接访问

✅ C++特有重点(和C对比)

static局部变量:不在栈!在data/bss,只初始化一次,生命周期全程。

void func(){

static int x = 5; // .data

int y = 5; // 栈

}

类里面:

普通成员变量:跟着对象走;对象new出来 → 在堆;局部对象 → 在栈

static成员变量:全局静态区(data/bss),不属于某个对象

成员函数代码:全部放在 .text

虚函数表 vtable:一般放在 rodata(只读段);虚指针vptr跟着对象(堆/栈)

📌 容易混淆区分表

变量位置函数本身、类成员函数.text字符串字面量、全局const常量.rodata初始化非0全局/static.data零初始化/未初始化全局/static.bssnew/malloc出来对象堆普通局部变量、局部对象、函数形参栈static局部变量.data/.bss📖 背诵精简版(面试口述)

C++进程虚拟内存从低到高:代码段、只读段rodata、data段、bss段、堆、mmap区、栈。

堆向高地址增长,栈向低地址增长;static变量在静态区,局部变量在栈,new在堆,字符串常量在rodata。

❓ 坑

不要把C++的内存五大区旧说法(栈、堆、全局静态区、常量区、代码区)和ELF段混起来,两种说法都对:

简化五大区(很多C++教材):代码区、常量区、全局静态区、堆、栈

ELF细分:text、rodata、data、bss、heap、mmap、stack

返回列表