为什么C的数据段被分成两部分?

2024-04-29

所有全局初始化值都存储在.data段,即已初始化的数据段和未初始化的值存储在bss编译器将这些未初始化的值自动初始化为零bss. Then why data段被分隔为.data and bss.

是否有优势?或者有什么好处?


C 编程语言(它是用英语编写的规范)不知道.bss or .data or 数据段 https://en.wikipedia.org/wiki/Data_segments。通过阅读来检查n1570 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf(最新草案C11 https://en.wikipedia.org/wiki/C11_(C_standard_revision)).

在某些情况下(例如嵌入式计算),您没有任何数据段。例如当你交叉编译 https://en.wikipedia.org/wiki/Cross_compiler for an Arduino https://www.arduino.cc/,生成的代码被上传到该微控制器的闪存(数据位于 RAM 中,您的程序可能会明确地 clear).

(most of my answer below is focused on Linux, but you could adapt it to other OSes)

关于数据段 https://en.wikipedia.org/wiki/Data_segment在 Linux 等类 Unix 系统上,请阅读更多规范ELF https://en.wikipedia.org/wiki/Executable_and_Linkable_Format. It is 方便的以避免花费文件空间可执行文件 https://en.wikipedia.org/wiki/Executable为某事归档(.bss https://en.wikipedia.org/wiki/.bss)全为零。这kernel https://en.wikipedia.org/wiki/Kernel_(operating_system)代码为执行(2) http://man7.org/linux/man-pages/man2/execve.2.html能够设置一个初始虚拟地址空间 https://en.wikipedia.org/wiki/Virtual_address_space一些清除的数据(即not 映射到某个文件 https://en.wikipedia.org/wiki/Memory-mapped_file部分)。也可以看看mmap(2) http://man7.org/linux/man-pages/man2/mmap.2.html & elf(5) http://man7.org/linux/man-pages/man5/elf.5.html & ld-linux(8) http://man7.org/linux/man-pages/man8/ld-linux.8.html。试一些cat /proc/$$/maps命令来了解 shell 的虚拟地址空间。看proc(5) http://man7.org/linux/man-pages/man5/proc.5.html.

所以可执行文件包含segments https://en.wikipedia.org/wiki/Memory_segmentation(其中一些全为零,不占用任何磁盘空间),并且由linker https://en.wikipedia.org/wiki/Linker_(computing)- 还可以处理搬迁 https://en.wikipedia.org/wiki/Relocation_(computing)- 来自几个目标文件 https://en.wikipedia.org/wiki/Object_file由提供compiler https://en.wikipedia.org/wiki/Compiler from 源代码 https://en.wikipedia.org/wiki/Source_code文件。在 Linux 上,使用对象转储(1) http://man7.org/linux/man-pages/man1/objdump.1.html and 雷德尔夫(1) http://man7.org/linux/man-pages/man1/readelf.1.html (and nm(1) http://man7.org/linux/man-pages/man1/nm.1.html...)来探索和检查 ELF 可执行文件和 ELF 目标文件。

顺便说一句,清除的数据段不需要由虚拟内存 https://en.wikipedia.org/wiki/Virtual_memory子系统,这可能会使事情slightly快点。内核只会清除一个page https://en.wikipedia.org/wiki/Page_(computer_memory)当它在 RAM 中时paged https://en.wikipedia.org/wiki/Paging in.

So the .bss存在是为了避免浪费可执行文件中的磁盘空间(并加速归零数据的初始化)。显然,一些可变数据被显式初始化为非零内容(并且需要位于.data并在可执行文件中占用一些磁盘空间)。恒定的不可变只读数据进入.rodata(进入文本段 https://en.wikipedia.org/wiki/Code_segment#rodata,一般由几个人共享流程 https://en.wikipedia.org/wiki/Process_(computing)运行相同的程序)

您可以配置您的链接器(例如使用某些链接器script https://sourceware.org/binutils/docs/ld/Scripts.html)将所有数据(甚至是清除的数据)放入一些显式的数据段 https://en.wikipedia.org/wiki/Data_segment(但这样做只是浪费磁盘空间)……从历史上看,Unix已经开发出来了 https://en.wikipedia.org/wiki/History_of_Unix on machines https://en.wikipedia.org/wiki/PDP-11#Unibus_models磁盘空间很少但成本高昂(因此浪费它在当时是不可想象的,因此需要.bss;今天你不在乎了!)

读莱文的书链接器和加载器 http://iecc.com/linkers/了解更多,以及高级Linux编程 http://advancedlinuxprogramming.com/ and 操作系统:三个简单的部分 http://pages.cs.wisc.edu/~remzi/OSTEP/.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么C的数据段被分成两部分? 的相关文章

  • OpenGL纹理渲染与原始不匹配

    我正在尝试使用 OpenGL 渲染纹理 我用作测试的纹理是白色背景上的一堆黑色矩形 如下所示 然而 在渲染时 纹理似乎被复制并叠加在其自身之上多次 我使用以下方法设置场景 std string vertexSource ShaderLoad
  • C# AES Rijndael - 检测无效密码

    我正在使用 Rijndael 加密程序中的一些敏感数据 当用户输入错误的密码时 大多数情况下CryptographicException抛出消息 填充无效且无法删除 然而 CryptStream 不会抛出密码错误的异常 而是返回错误解密的流
  • ZedGraph 缩放和调整大小

    当我绘制图形 放大和缩小并重新绘制图形时 图形的位置不会改变 我想要做的是 每当重新绘制数据时 视图都会更改以查看所有图形数据 如果您在重绘之前放大或缩小 这似乎会被禁用 Thanks 设置属性 IsZoomOnMouseCenter对于控
  • 无法在更新面板中找到上传的文件

    aspx
  • 函数原型和数组参数

    我正在学习 C 语法 并且已经开始研究数组了 我想问你一个问题 但首先让我回顾一下 这样我就知道我已经弄清楚了 我知道您可以使用以下语法将变量定义为数组 name
  • 使用 boost::iterator_facade<>

    我有一个链表结构 struct SomeLinkedList const char bar int lots of interesting stuff in here DWORD foo SomeLinkedList pNext 它是现有
  • 设置外部应用程序焦点

    在 VB NET 中 您可以使用以下命令将焦点设置到外部应用程序 AppActivate Windows Name or AppActivate processID As Integer 现在 如果您这样做 则效果很好 Dim intNot
  • 在 DefaultHttpContext 上使用 FeatureCollection 时,响应对象为 null

    我正在测试一些 net Core 中间件 并希望使用整个 asp net Core http 管道来运行中间件 而不是模拟它 问题是 当我使用特征集合时 不知何故 响应对象没有在 httpRequest 中设置 并且它在请求本身上是只读的
  • 为什么测试在 TeamCity 中运行比直接在 NUnit 中运行需要更长的时间?

    我进行了一些 C 性能测试 基本上运行两种不同的方法 并检查一种方法的运行速度是否比另一种方法快得多 当我在 NUnit 本地运行它们时 其中一个测试的运行速度是另一个测试的十倍 因此我有一个 NUnit 测试 它使用Stopwatch检查
  • 使用 MapViewOfFile 有什么限制吗?

    我正在尝试将内存映射文件用作 hFile CreateFile State Path GENERIC READ FILE SHARE READ FILE SHARE WRITE 0 OPEN EXISTING FILE FLAG SEQUE
  • 最小对的总和

    Given 2N点 in a 2D plane 你必须将它们分组为N pairs使得所有对的点之间的距离的总和是最小可能值 所需的输出只是总和 换句话说 如果a1 a2 an分别是第一对 第二对 和第 n 对点之间的距离 则 a1 a2 a
  • 适用于 Windows 的键值数据库?

    除了 MongoDB 和 Memcached 之外 Windows 上还运行哪些键值存储 我见过的大多数似乎只能在 Linux 上运行 Hypertable Redis Lightcloud 相关链接 是否有经过商业验证的云存储 Key g
  • 复杂的 C 声明

    我刚刚在互联网上浏览了一些代码 发现了这个 float foo SIZE SIZE 我如何阅读这份声明 是否有一套特定的规则来阅读如此复杂的声明 我有一段时间没做这个了 从 开始foo然后向右走 float foo SIZE SIZE fo
  • C# Linq 可以做组合数学吗?

    我有这个数据结构 class Product public string Name get set public int Count get set var list new List
  • DLL 中的 XP 风格组合框

    我需要使用 C 和 WIN32 API 无 MFC 在 DLL 中创建 XP 风格的组合框 我设法在 DLL 中创建控件 不是以 XP 风格 我设法在带有清单的 exe 中创建 XP 样式组合框 但它在 DLL 中不起作用 为了让您的 DL
  • C语言:如何获取使用strtok()一次后剩余的字符串

    我的字符串是 A B C D E 分隔符是 如何获取执行 strtok 一次后剩余的字符串 即 B C D E char a A B C D E char separator char b strtok a separator printf
  • 如何通过Task.ContinueWith创建传递?

    我想在原始任务结束时添加一个任务 但想保留原始结果和类型 附加任务仅用于记录目的 例如写入控制台等 例如 Task Run gt DateTime Now Hour gt 12 Hey throw new Exception Continu
  • 字符串常量之前应有非限定 ID

    我目前正在编写一个 C 应用程序 它与 math h 结合实现了振荡器 我拥有的代码应该可以很好地用于该应用程序 尝试编译目标文件 但是我遇到编译器错误 很可能与语法 等有关 我认为这与命名空间有关 错误 终端输出 User Name Ma
  • Selenium WebDriver 在按钮单击事件上无法正常工作。这里有什么问题呢?

    I am using following code to scrape data from a website I have following interface 这是 HTML div class es content div
  • “保留供任何使用”是什么意思?

    注意 这是一个c questions tagged c问题 虽然我补充说c questions tagged c 2b 2b如果某些 C 专家可以提供 C 使用与 C 不同的措辞的基本原理或历史原因 在 C 标准库规范中 我们有这个规范文本

随机推荐