学习总结与data/bss
2026/8/25 14:05:55 网站建设 项目流程

目录

前言

什么是 .data 段(运行时视角)

什么是 .bss 段(运行时视角)

.data 与 .bss 对比

static 局部变量落在哪个段

磁盘 ELF 段 和 进程内存段的区别

.data/.bss 的生命周期与释放时机

.data/.bss 总结


前言

AI问答式记录,比较详细

什么是 .data 段(运行时视角)

.data属于进程静态存储区,位于进程虚拟地址空间内。

✅进入.data的两个必要条件,必须同时满足

  1. 变量:全局变量 或者static静态变量
  2. 初始化:显式赋值非 0 的初始值

🟡重点提醒 函数内部普通局部变量开辟在栈帧,永远不会进入.data

表格

对比项.data 段
内存归属静态存储区(虚拟内存)
可存放变量全局、static,初值不为 0
内存权限可读、可写、不可执行
磁盘 ELF 行为保存变量初始数据,占用磁盘空间

c

int g_a = 100; // 全局,非0初值 → .data static int s_b = 200; // static,非0初值 → .data void func() { int l_c = 10; // 局部变量 → 栈 }

📝自测

static int num = 60;该变量存放在哪个段?

  1. .data 的变量数据是怎么来到内存中的?
  2. 函数中普通局部变量会不会存放在.data

1.data

2. 映射虚拟内存

3.不会

✅批改

  1. .data正确
  2. 不完全准确:磁盘 ELF 文件保存着初始数值,程序加载时把磁盘上的数据拷贝到内存,不只是单纯映射虚拟内存。虚拟地址只是地址,真实数据来源于可执行文件。
  3. 不会 正确,局部变量在栈帧。

什么是 .bss 段(运行时视角)

.bss同样属于进程静态存储区,处在虚拟地址空间。

✅进入.bss的两个必要条件,必须同时满足

  1. 变量:全局变量 或者static静态变量
  2. 初始化:不写初始化,或者显式赋值为 0

🟡重点提醒 函数内部普通局部变量开辟在栈帧,永远不会进入.bss

表格

对比项.bss 段
内存归属静态存储区(虚拟内存)
可存放变量全局、static,未初始化 / 初值等于 0
内存权限可读、可写、不可执行
磁盘 ELF 行为不存储变量有效数据,几乎不占用磁盘空间

c

int g_x; // 全局未初始化 → .bss static int s_y = 0; // static显式赋值0 → .bss void func() { int l_z; // 局部变量 → 栈 }

📝自测

  1. static int val = 0;该变量存放在哪个段?
  2. .bss 段在 ELF 磁盘文件中保存变量的实际数值吗?
  3. 函数内部普通局部变量会不会存放在.bss

1.bss

2.不会

3.不会

✅批改

  1. .bss正确
  2. 不会 正确,.bss不在 ELF 中存放实际数值,仅记录需要多大内存
  3. 不会 正确,局部变量在栈帧

🟡小结.bss只记录内存大小信息,磁盘几乎不占空间;程序加载后操作系统把这一块内存整体清零。


.data 与 .bss 对比

二者都属于静态存储区,位于进程虚拟地址空间。局部变量存栈,和这两个段无关。

表格

对比项目.data.bss
接收变量全局 /static,初值非 0全局 /static,未初始化 或初值 = 0
ELF 磁盘文件保存变量初始值,占用磁盘空间仅记录内存大小,不存真实数值,几乎不占磁盘
内存数据来源把磁盘的数据拷贝到内存操作系统加载后整块内存置 0
内存权限可读、可写、不可执行可读、可写、不可执行

🟡高频易错点int g = 0;,就算手动写赋值 0,依然归属于.bss,不属于.data

c

int a = 10; // .data static int b; // .bss int c = 0; // .bss void test() { int d = 5; // 栈 }

📝自测

  1. int global = 0;该全局变量属于哪一个段?
  2. 下列哪一项是.data的特点: A、磁盘不保存数据 B、从 ELF 拷贝初值到内存 C、用来存放栈变量
  3. 判断:局部 static 变量有可能落到 .bss 或者 .data(对 / 错)

1.dss

2.B

3.对

✅批改

  1. 笔误,是.bss,结论正确。int global = 0;初值为 0,进入.bss
  2. B 正确,.data会将 ELF 里面保存的初值拷贝进内存
  3. 对 正确。局部static本质是静态变量:初值非 0 进.data;初值为 0 / 不初始化进.bss

🟡小结static修饰的局部变量,不在栈上,放到静态存储区(.data/.bss),函数结束不会销毁。


static 局部变量落在哪个段

普通局部变量在栈帧,函数调用结束栈回收,变量直接销毁。 被static修饰的局部变量,不再存放在栈中,放到静态存储区。

✅分配规则

  1. static 局部变量,显式非 0 初始化 →.data 段
  2. static 局部变量,不初始化 / 初始化为 0 →.bss 段

🟡重点

  • 生命周期:随整个进程,函数退出不会销毁,保留上一次的值
  • 作用域:依旧只能在定义它的函数内部使用,别的函数不能直接访问

表格

变量类型存储位置生命周期
普通局部变量栈帧函数调用期间
static 局部变量.data / .bss整个进程运行周期

c

void func(void) { static int s1 = 10; //非0初值 → .data static int s2 = 0; //初值0 → .bss static int s3; //未初始化 → .bss int normal; //普通局部 → 栈 }

📝自测

  1. static int a = 5;写在函数内部,该变量存放在哪个段?
  2. static 局部变量,函数调用结束之后,变量会销毁吗?
  3. 判断:static 局部变量别的函数可以直接访问(对 / 错)

1. data

2.不会

3.错

✅批改

  1. .data正确,非 0 初始化的 static 局部变量存放在.data 段
  2. 不会 正确,存放在静态存储区,进程结束才销毁,函数退出会保留数值
  3. 错 正确,作用域仅限于当前函数,外部函数不能直接访问

🟡小结 static 局部变量:存储位置在静态区,作用域局限于函数内,这是最容易混淆的考点。


磁盘 ELF 段 和 进程内存段的区别

写好的 C 程序编译链接之后得到ELF 可执行文件,存放在磁盘。 当程序运行,操作系统把 ELF 加载,才形成进程的虚拟地址空间。

🟡关键区分

  • 磁盘:是文件,存在硬盘上
  • 进程虚拟内存:程序跑起来之后,操作系统给进程分配的虚拟地址空间

表格

对象.data.bss
磁盘 ELF 文件占用磁盘,存放变量初始值几乎不占磁盘,只记录需要的内存大小
运行之后内存映射到虚拟内存,数据从 ELF 拷贝过来虚拟内存分配空间,操作系统置 0

⚠️非常容易踩坑:.bss在磁盘里根本没有存放变量数据,只有程序运行起来之后,内存才会有这一块空间

c

int g_val1 = 20; //磁盘.data段保存20,运行加载到内存.data int g_val2; //磁盘不存数值,仅记录大小,运行分配到内存.bss并清零

📝自测

  1. ELF 磁盘文件中,.bss是否存储变量实际的值?
  2. .data段变量初始值来自哪里?
  3. 判断:.bss 拥有磁盘文件存储空间(对 / 错)

1.否

2.EIF文件

3.错

✅批改

  1. 否 正确,磁盘 ELF 的.bss 只记录内存尺寸,不存变量真实数值
  2. ELF 文件 正确,程序加载时把 ELF 里保存的初值拷贝进内存
  3. 错 正确,.bss不占用 ELF 有效存储空间

🟡小结 磁盘上 ELF 的段 ≠ 运行时内存段。.bss 属于 “运行时才创造出来” 的内存空间,磁盘文件不给它存数据。


.data/.bss 的生命周期与释放时机

.data.bss的变量全部属于静态存储区

  • 分配时机:程序加载运行的时候,操作系统就为它们分配虚拟内存。
  • 生命周期:贯穿整个进程的全部运行时间
  • 释放时机:进程结束退出操作系统回收内存。函数调用、函数返回,不会回收这两块内存。

🟡区分对比 普通局部变量(栈):函数调用开辟,函数结束立刻回收。 .data/.bss 变量:不受函数进出影响。

表格

.data / .bss栈局部变量
分配程序加载时函数调用时
释放进程结束函数执行完毕
生存时间整个进程单次函数调用

c

void count(void) { static int cnt = 0; // .bss,函数退出不会销毁,数值保留 cnt++; } int g = 10; // .data,全程存活

📝自测

  1. .data、.bss 中变量什么时候释放内存?
  2. 函数返回之后,static 静态变量的值会丢失吗?
  3. 判断:进入函数才分配.data 段变量的内存(对 / 错)

1.程序结束

2.不会

3.错

✅批改

  1. 程序结束 正确,进程退出操作系统回收.data/.bss的内存
  2. 不会 正确,static 变量存静态存储区,函数返回值保留
  3. 错 正确,程序加载的时候就完成内存分配,不是调用函数才分配

🟡小结 栈随函数生灭;.data.bss跟随整个进程,和函数调用无关。


.data/.bss 总结

  1. 什么样的变量才会进.data/.bss只有全局变量、static 修饰变量。普通局部变量在栈,跟这两个段无关。

  2. 归属判定规则

  • 全局 /static,显式非 0 初始化 →.data
  • 全局 /static,未初始化 或者初始化为 0 →.bss
  1. 磁盘 ELF 与内存差异
  • .data:ELF 磁盘保存初始值,程序加载拷贝到内存。
  • .bss:磁盘上不存放数据,仅记录需要内存大小;运行时分配虚拟内存,操作系统统一清零。
  1. 生命周期都属于静态存储区,程序加载就分配内存,进程结束才释放,不受函数调用‑返回影响。

c

int A = 10; // .data int B = 0; // .bss int C; // .bss void test(){ static int D = 20; // .data static int E = 0; // .bss int F; // 栈 }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询