C(64位)中的内存分配布局问题

时间:2019-02-20 06:45:29

标签: c memory-layout data-segment

我想了解“ C”程序如何运行并将数据存储在计算机中。 因此,我从here看了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。这个。

第二季度:但是,当我添加static int x时,它不再是在bss中添加了内存块。这是预期的吗?

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

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

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

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

Arigato:)

2 个答案:

答案 0 :(得分:1)

  

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

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

的总和
  

但是当我添加静态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也增加了。为什么?

因为dectextdatabss的总和

答案 1 :(得分:0)

这里是一个简短的摘要:

  • 可执行代码,字符串文字和常量全局变量被加载到 text 段,该段由支持它的系统上的OS程序加载器在内存中设为只读。

  • 使用static存储声明的全局初始化的可修改对象和本地初始化的对象将被加载到 data 段中。

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

  • 具有自动存储功能的其他本地对象是在功能进入时从 stack 段动态雕刻的,有时它们会在进入范围时动态运行。

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

  • 十六进制 dec 的十六进制表示形式。

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

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

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

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

现代操作系统处理有关可执行程序的更多细分和复杂问题,以上是一种简单的方法,用于对1970年代和1980年代早期Unix系统中的可执行程序的内存布局进行建模。这些名称比Unix早了将近20年。可以使用 objdump nm 实用工具显示更多信息。

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

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

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

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