学习总结与data/bss

📅 2026/8/25 14:06:02
学习总结与data/bss
目录前言什么是 .data 段运行时视角什么是 .bss 段运行时视角.data 与 .bss 对比static 局部变量落在哪个段磁盘 ELF 段 和 进程内存段的区别.data/.bss 的生命周期与释放时机.data/.bss 总结前言AI问答式记录比较详细什么是 .data 段运行时视角.data属于进程静态存储区位于进程虚拟地址空间内。✅进入.data的两个必要条件必须同时满足变量全局变量 或者static静态变量初始化显式赋值非 0 的初始值重点提醒 函数内部普通局部变量开辟在栈帧永远不会进入.data。表格对比项.data 段内存归属静态存储区虚拟内存可存放变量全局、static初值不为 0内存权限可读、可写、不可执行磁盘 ELF 行为保存变量初始数据占用磁盘空间cint g_a 100; // 全局非0初值 → .data static int s_b 200; // static非0初值 → .data void func() { int l_c 10; // 局部变量 → 栈 }自测static int num 60;该变量存放在哪个段.data 的变量数据是怎么来到内存中的函数中普通局部变量会不会存放在.data1.data2. 映射虚拟内存3.不会✅批改.data正确不完全准确磁盘 ELF 文件保存着初始数值程序加载时把磁盘上的数据拷贝到内存不只是单纯映射虚拟内存。虚拟地址只是地址真实数据来源于可执行文件。不会 正确局部变量在栈帧。什么是 .bss 段运行时视角.bss同样属于进程静态存储区处在虚拟地址空间。✅进入.bss的两个必要条件必须同时满足变量全局变量 或者static静态变量初始化不写初始化或者显式赋值为 0重点提醒 函数内部普通局部变量开辟在栈帧永远不会进入.bss。表格对比项.bss 段内存归属静态存储区虚拟内存可存放变量全局、static未初始化 / 初值等于 0内存权限可读、可写、不可执行磁盘 ELF 行为不存储变量有效数据几乎不占用磁盘空间cint g_x; // 全局未初始化 → .bss static int s_y 0; // static显式赋值0 → .bss void func() { int l_z; // 局部变量 → 栈 }自测static int val 0;该变量存放在哪个段.bss 段在 ELF 磁盘文件中保存变量的实际数值吗函数内部普通局部变量会不会存放在.bss1.bss2.不会3.不会✅批改.bss正确不会 正确.bss不在 ELF 中存放实际数值仅记录需要多大内存不会 正确局部变量在栈帧小结.bss只记录内存大小信息磁盘几乎不占空间程序加载后操作系统把这一块内存整体清零。.data 与 .bss 对比二者都属于静态存储区位于进程虚拟地址空间。局部变量存栈和这两个段无关。表格对比项目.data.bss接收变量全局 /static初值非 0全局 /static未初始化 或初值 0ELF 磁盘文件保存变量初始值占用磁盘空间仅记录内存大小不存真实数值几乎不占磁盘内存数据来源把磁盘的数据拷贝到内存操作系统加载后整块内存置 0内存权限可读、可写、不可执行可读、可写、不可执行高频易错点int g 0;就算手动写赋值 0依然归属于.bss不属于.data。cint a 10; // .data static int b; // .bss int c 0; // .bss void test() { int d 5; // 栈 }自测int global 0;该全局变量属于哪一个段下列哪一项是.data的特点 A、磁盘不保存数据 B、从 ELF 拷贝初值到内存 C、用来存放栈变量判断局部 static 变量有可能落到 .bss 或者 .data对 / 错1.dss2.B3.对✅批改笔误是.bss结论正确。int global 0;初值为 0进入.bssB 正确.data会将 ELF 里面保存的初值拷贝进内存对 正确。局部static本质是静态变量初值非 0 进.data初值为 0 / 不初始化进.bss小结static修饰的局部变量不在栈上放到静态存储区.data/.bss函数结束不会销毁。static 局部变量落在哪个段普通局部变量在栈帧函数调用结束栈回收变量直接销毁。 被static修饰的局部变量不再存放在栈中放到静态存储区。✅分配规则static 局部变量显式非 0 初始化 →.data 段static 局部变量不初始化 / 初始化为 0 →.bss 段重点生命周期随整个进程函数退出不会销毁保留上一次的值作用域依旧只能在定义它的函数内部使用别的函数不能直接访问表格变量类型存储位置生命周期普通局部变量栈帧函数调用期间static 局部变量.data / .bss整个进程运行周期cvoid func(void) { static int s1 10; //非0初值 → .data static int s2 0; //初值0 → .bss static int s3; //未初始化 → .bss int normal; //普通局部 → 栈 }自测static int a 5;写在函数内部该变量存放在哪个段static 局部变量函数调用结束之后变量会销毁吗判断static 局部变量别的函数可以直接访问对 / 错1. data2.不会3.错✅批改.data正确非 0 初始化的 static 局部变量存放在.data 段不会 正确存放在静态存储区进程结束才销毁函数退出会保留数值错 正确作用域仅限于当前函数外部函数不能直接访问小结 static 局部变量存储位置在静态区作用域局限于函数内这是最容易混淆的考点。磁盘 ELF 段 和 进程内存段的区别写好的 C 程序编译链接之后得到ELF 可执行文件存放在磁盘。 当程序运行操作系统把 ELF 加载才形成进程的虚拟地址空间。关键区分磁盘是文件存在硬盘上进程虚拟内存程序跑起来之后操作系统给进程分配的虚拟地址空间表格对象.data.bss磁盘 ELF 文件占用磁盘存放变量初始值几乎不占磁盘只记录需要的内存大小运行之后内存映射到虚拟内存数据从 ELF 拷贝过来虚拟内存分配空间操作系统置 0⚠️非常容易踩坑.bss在磁盘里根本没有存放变量数据只有程序运行起来之后内存才会有这一块空间。cint g_val1 20; //磁盘.data段保存20运行加载到内存.data int g_val2; //磁盘不存数值仅记录大小运行分配到内存.bss并清零自测ELF 磁盘文件中.bss是否存储变量实际的值.data段变量初始值来自哪里判断.bss 拥有磁盘文件存储空间对 / 错1.否2.EIF文件3.错✅批改否 正确磁盘 ELF 的.bss 只记录内存尺寸不存变量真实数值ELF 文件 正确程序加载时把 ELF 里保存的初值拷贝进内存错 正确.bss不占用 ELF 有效存储空间小结 磁盘上 ELF 的段 ≠ 运行时内存段。.bss 属于 “运行时才创造出来” 的内存空间磁盘文件不给它存数据。.data/.bss 的生命周期与释放时机.data、.bss的变量全部属于静态存储区。分配时机程序加载运行的时候操作系统就为它们分配虚拟内存。生命周期贯穿整个进程的全部运行时间。释放时机进程结束退出操作系统回收内存。函数调用、函数返回不会回收这两块内存。区分对比 普通局部变量栈函数调用开辟函数结束立刻回收。 .data/.bss 变量不受函数进出影响。表格.data / .bss栈局部变量分配程序加载时函数调用时释放进程结束函数执行完毕生存时间整个进程单次函数调用cvoid count(void) { static int cnt 0; // .bss函数退出不会销毁数值保留 cnt; } int g 10; // .data全程存活自测.data、.bss 中变量什么时候释放内存函数返回之后static 静态变量的值会丢失吗判断进入函数才分配.data 段变量的内存对 / 错1.程序结束2.不会3.错✅批改程序结束 正确进程退出操作系统回收.data/.bss的内存不会 正确static 变量存静态存储区函数返回值保留错 正确程序加载的时候就完成内存分配不是调用函数才分配小结 栈随函数生灭.data、.bss跟随整个进程和函数调用无关。.data/.bss 总结什么样的变量才会进.data/.bss只有全局变量、static 修饰变量。普通局部变量在栈跟这两个段无关。归属判定规则全局 /static显式非 0 初始化 →.data全局 /static未初始化 或者初始化为 0 →.bss磁盘 ELF 与内存差异.dataELF 磁盘保存初始值程序加载拷贝到内存。.bss磁盘上不存放数据仅记录需要内存大小运行时分配虚拟内存操作系统统一清零。生命周期都属于静态存储区程序加载就分配内存进程结束才释放不受函数调用‑返回影响。cint A 10; // .data int B 0; // .bss int C; // .bss void test(){ static int D 20; // .data static int E 0; // .bss int F; // 栈 }