C(64 位)中的内存分配布局问题
Memory allocation layout issues in C (64-bit)
我想了解 "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
第一个问题:
负责内存分配的因素(hardware/software)是什么?
布局中的 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-64 位)的内存块被添加到 bss
所以它从 2640 变成了 2656(第一个例子)我明白了。
Q2:但是当我添加 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 中是如何工作的。
阿里加托:)
What are the factors (Hardware/Software) that are responsible for the memory allocation?. And what does dec in the layout refer to
你的程序在运行时分成了很多段。 stack
包含局部变量。 bss data
包含 未初始化的 全局变量。 initialized data
包含初始化的全局变量。 text
包含您的文本(代码)。
dec
是 text
、bss
、data
的总和
But when i add the static int x it is not adding the memory block to bss anymore.is it expected?
保持它未初始化然后它会添加。
添加静态变量前:
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
And finally when i initialize the global variable with 20, data got incremented (expected) and dec also got incremented. Why?
因为dec
是text
、data
、bss
的总和
这里是一个简短的总结:
可执行代码、字符串文字和常量全局变量被加载到 text 段,[=101= 在内存中将其设置为只读] 支持它的系统上的程序加载器。
全局初始化的可修改对象和用static
存储声明的局部初始化对象加载到数据段。
未初始化的可修改全局对象和未初始化的局部static
对象分配在bss段中,可执行文件中不存在。
其他具有自动存储功能的本地对象是在函数输入时从 堆栈 段动态雕刻的,有时当它们进入作用域时会在运行中。
dec列给出了程序代码和数据的总大小:text,data 和 bss。这不包括在启动时分配的内存、堆栈 space,也不包括从堆或使用其他 OS 特定方法动态分配的数据。
hex是dec的十六进制表示。
这些值因操作系统、编译器、编译器设置和库而异。该网站显示系统 运行 CentOS 上的输出,可能处于 32 位模式。请注意同一程序如何为所有段生成更大的值,这主要是由于不同的 C 库启动代码。 main
函数本身应该使用几个字节到最多几十个字节,具体取决于编译选项。
可执行文件的大小与 dec 不同,因为它不包含 bss 数据,但包含有关如何执行的其他信息加载程序:各个段的大小和位置、对动态库的引用和来自它们的 link 的符号、调试信息等
添加全局变量时,未初始化的bss增加,否则data增加。添加局部变量时,如果它是静态的,也会发生同样的情况。
但请注意,对齐问题可能会影响数据添加到段的方式,优化设置可能会影响新对象是否实际添加到可执行文件中。如果编译器可以确定一个对象从未被使用过,它可能会完全忽略它。
现代操作系统处理更多关于可执行程序的段和复杂性,以上是一种简单的方法,它模拟了 1970 年代和 80 年代早期 Unix 系统中可执行程序的内存布局。这些名称早于 Unix 将近 2 年。可以使用 objdump 和 nm 实用程序显示更多信息。
您可以在此处阅读有关标准 Unix 段名称的详细说明:
文本: https://en.wikipedia.org/wiki/Code_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
第一个问题:
负责内存分配的因素(hardware/software)是什么?
布局中的 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-64 位)的内存块被添加到 bss
所以它从 2640 变成了 2656(第一个例子)我明白了。
Q2:但是当我添加 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 中是如何工作的。
阿里加托:)
What are the factors (Hardware/Software) that are responsible for the memory allocation?. And what does dec in the layout refer to
你的程序在运行时分成了很多段。 stack
包含局部变量。 bss data
包含 未初始化的 全局变量。 initialized data
包含初始化的全局变量。 text
包含您的文本(代码)。
dec
是 text
、bss
、data
But when i add the static int x it is not adding the memory block to bss anymore.is it expected?
保持它未初始化然后它会添加。
添加静态变量前:
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
And finally when i initialize the global variable with 20, data got incremented (expected) and dec also got incremented. Why?
因为dec
是text
、data
、bss
这里是一个简短的总结:
可执行代码、字符串文字和常量全局变量被加载到 text 段,[=101= 在内存中将其设置为只读] 支持它的系统上的程序加载器。
全局初始化的可修改对象和用
static
存储声明的局部初始化对象加载到数据段。未初始化的可修改全局对象和未初始化的局部
static
对象分配在bss段中,可执行文件中不存在。其他具有自动存储功能的本地对象是在函数输入时从 堆栈 段动态雕刻的,有时当它们进入作用域时会在运行中。
dec列给出了程序代码和数据的总大小:text,data 和 bss。这不包括在启动时分配的内存、堆栈 space,也不包括从堆或使用其他 OS 特定方法动态分配的数据。
hex是dec的十六进制表示。
这些值因操作系统、编译器、编译器设置和库而异。该网站显示系统 运行 CentOS 上的输出,可能处于 32 位模式。请注意同一程序如何为所有段生成更大的值,这主要是由于不同的 C 库启动代码。 main
函数本身应该使用几个字节到最多几十个字节,具体取决于编译选项。
可执行文件的大小与 dec 不同,因为它不包含 bss 数据,但包含有关如何执行的其他信息加载程序:各个段的大小和位置、对动态库的引用和来自它们的 link 的符号、调试信息等
添加全局变量时,未初始化的bss增加,否则data增加。添加局部变量时,如果它是静态的,也会发生同样的情况。
但请注意,对齐问题可能会影响数据添加到段的方式,优化设置可能会影响新对象是否实际添加到可执行文件中。如果编译器可以确定一个对象从未被使用过,它可能会完全忽略它。
现代操作系统处理更多关于可执行程序的段和复杂性,以上是一种简单的方法,它模拟了 1970 年代和 80 年代早期 Unix 系统中可执行程序的内存布局。这些名称早于 Unix 将近 2 年。可以使用 objdump 和 nm 实用程序显示更多信息。
您可以在此处阅读有关标准 Unix 段名称的详细说明:
文本: https://en.wikipedia.org/wiki/Code_segment