1

我想了解“C”程序如何运行并将数据存储在机器中。所以我从这里查看了 C 的内存布局,并在我的 64 位机器上遵循了相同的指令。

首先,当我编写程序(main只有return 0;)并使用size可执行文件的命令时:它在文本和数据段中显示出很多差异。

text    data    bss     dec     hex     filename
10648   2400    2640    15688   3d48    33.exe

但在上面提到的网站上显示:

text    data    bss     dec     hex     filename
960     248     8       1216    4c0     memory-layout

第一个问题: 负责内存分配的因素(硬件/软件)是什么?dec布局中指的是什么?/问题到此结束

但首先我忽略了这一点并开始声明变量(全局和静态)以查看它们的存储位置。我在这个阶段面临一个问题。

对于此代码:

#include <stdio.h> 
int global;  
int main(void) {
    //static int x;
    return 0; 
} 

我得到的输出为:

text    data    bss     dec     hex     filename
10648   2400    2656    15704   3d48    33.exe

那是因为我声明(未初始化)一个全局变量,这就是为什么将 16 个字节(int-64bit)的内存块添加到它bss所以它从 2640 变成 2656(第一个示例)我理解这一点。

Q2:但是当我添加static int x它时,它不再添加内存块bss。这是预期的吗?

text    data    bss     dec     hex     filename
10648   2400    2656    15704   3d48    33.exe 

Q3:最后当我用 初始化全局变量时20data增加(预期)并且dec也增加了为什么?

text    data    bss     dec     hex     filename
10648   2416    2656    15720   3d48    33.exe

我知道我在这里问了很多问题,但我想知道这种内存管理在 C 中是如何工作的。

阿里加托:)

4

2 回答 2

1

负责内存分配的因素(硬件/软件)是什么?布局中的 dec 指的是什么

您的程序在运行时分为许多部分。stack包含局部变量。bss data包含未初始化的全局变量。initialized data包含初始化的全局变量。text包含您的文本(代码)。 dectext, bss,的总和data

但是,当我添加静态 int x 时,它不再将内存块添加到 bss。这是预期的吗?

保持它未初始化,然后它会添加。

添加静态变量之前:

   text    data     bss     dec     hex filename
   1099     544       8    1651     673 a.out

添加静态变量后:

   text    data     bss     dec     hex filename
   1099     544      16    1659     67b a.out

最后,当我用 20 初始化全局变量时,数据增加(预期)并且 dec 也增加了。为什么?

因为dectext, data,的总和bss

于 2019-02-20T07:34:33.873 回答
0

这是一个快速的总结:

  • 可执行代码、字符串文字和常量全局变量被加载到文本段,在支持它的系统上,操作系统程序加载器在内存中将其设置为只读。

  • 用 storage 声明的全局初始化的可修改对象和局部初始化的对象static被加载到数据段中。

  • 未初始化的可修改全局对象和未初始化的局部static对象分配在bss段中,可执行文件中不存在。

  • 其他具有自动存储功能的本地对象是在函数进入时从堆栈段动态雕刻的,有时当它们进入作用域时会在运行中进行。

  • dec列给出了程序代码和数据的总大小:text databss总和。这不包括在启动时分配的内存、堆栈空间,也不包括从堆中动态分配或使用其他操作系统特定方法分配的数据。

  • hexdec的十六进制表示。

这些值因操作系统、编译器、编译器设置和库而异。该网站显示了运行 CentOS 的系统上的输出,可能是 32 位模式。请注意同一程序如何为所有段生成更大的值,这主要是由于不同的 C 库启动代码。函数本身应该使用main几个字节到最多几十个,具体取决于编译选项。

可执行文件的大小与dec不同,因为它不包含bss数据,但包含有关如何加载程序的其他信息:各个段的大小和位置、对动态库的引用以及从它们链接的符号, 调试信息等

添加全局变量时,如果未初始化,则bss增加,否则数据增加。添加局部变量时,如果它是静态的,也会发生同样的情况。

但是请注意,对齐问题可能会影响数据添加到段的方式,优化设置可能会影响新对象是否实际添加到可执行文件中。如果编译器可以确定一个对象从未被使用过,它可能会完全忽略它。

现代操作系统处理更多关于可执行程序的部分和复杂性,以上是一种简化的方法,它模拟了 1970 年代和 1980 年代早期 Unix 系统中可执行程序的内存布局。这些名称比 Unix 早了近 2 个十年。可以使用objdumpnm实用程序显示更多信息。

您可以在此处阅读有关标准 Unix 段名称的详细说明:

文本https ://en.wikipedia.org/wiki/Code_segment

数据https ://en.wikipedia.org/wiki/Data_segment

bsshttps ://en.wikipedia.org/wiki/.bss

于 2019-02-20T08:01:16.410 回答