2017-04-07 69 views
0

我知道全局数据将存储在.BSS或.data段中。启动时存储的函数内部定义的本地数据在哪里

但是,如果我在函数内部定义了一些结构数据(如结构体),那么只有在调用该函数时才会将该结构放置在堆栈上。

在函数调用之前,编译器在启动时何处存储此数据? 我知道编译器会根据目标和调用约定等生成不同的汇编代码,但通常情况下,这个局部结构不会先存储在某处,以便编译器知道如何在函数返回时将其放在堆栈上叫什么名字?提前致谢。

+0

如果你的意思是局部变量被初始化,那么初始化确实必须存储在某个地方(很可能是数据段),除非它非常简单(可能全部字节为零)。但这是C调用函数时未将本地(自动)变量设置为预定值的原因的一部分;需要时间/空间来处理通常会被覆盖的初始化。 –

+0

但是,它是如何知道每次调用结构时都会将结构放在那里,大小,偏移量等等?这些信息是否存储在某个地方? – Engineer999

+0

是的,它存储在某个地方 - 我建议它可能是数据部分,但是我没有在您的机器上解析生成的汇编语言以查看它是如何完成的;事实上,我没有检查我的机器)。编译器/链接器的工作是确保它正确地发生。该标准没有规定必须如何完成;它只是强制要达到这个效果。 –

回答

0

在全局变量(也是静态本地)的情况下:
编译器访问全局变量作为特定地址和大小的内存部分。地址最初是一个占位符(很像变量的名称)。大小是隐含的,取决于编译器在汇编/机器代码中选择了哪种访问类型。链接器/加载器知道大小,它确保下一个变量不重叠。
地址占位符在链接(例如嵌入式,静态,就地执行)或加载(例如PC上的应用程序,应用程序)期间被替换。

在局部变量的情况下:
“地址”的值,它被写入到占位符,是相对的,对在启动函数的时间堆叠位置的“顶部”的偏移量。
其他方式与全球占位符的值相同。堆栈中的位置受访问哪个变量的影响,可选地为结构成员使用子偏移量。实际地址被确定为堆栈位置(即堆栈指针的值)加上在占位符中找到的相对偏移量。

占位符实际上是偏移量列表,存储在一个二进制文件(例如program.exe)中,以及实际的二进制代码。就像“当你决定在内存中找到这个变量的位置,然后在这里列出的代码中的所有地方写下地址:...”。写入这些地方将例如在一个字节中放置一个有意义的值,该字节在执行期间将被解释为相对“MOV”汇编程序指令的文字偏移量;相对于例如一个指向BSS段开始的段指针。

简而言之,地址信息在占位符列表中。这些列表migth根本不在内存中找到,或者不在执行时。一旦程序被加载(包括填充占位符),这些列表就不再需要了。
大小信息是代码的一部分(例如,使用8位访问或32位访问),它是可变位置布局的一部分。在前面的变量之后,每个访问都足够远。

因此,即使更短,您所查找的信息在执行过程中一半隐藏,一半不在内存中。

我假设你的问题不是关于变量内的值。只是为了掩饰它:该值被初始化为0,一个不变的初始化值,或者特殊情况,根本不存在,在启动时保留内存中的任何内容。 init值在基本上是常量列表的部分中找到。找到给定变量的常量的位置与占位符相似。
在局部变量的情况下,编译器通常不会初始化,但可以配置为写入0(这是一种“昂贵的”)。这就是为什么在使用它们之前初始化变量是很好的做法。具有显式初始化的局部变量当然是在堆栈帧设置期间初始化的。