【问题标题】:Where is local data defined inside a function stored at startup启动时存储的函数内部定义的本地数据在哪里
【发布时间】:2017-09-02 08:52:21
【问题描述】:

我了解全局数据将存储在 .BSS 或 .data 段中。

如果我在函数内部定义了诸如结构之类的数据,则该结构只会在调用该函数时被放置在堆栈中。

在调用函数之前,编译器在启动时将这些数据存储在哪里? 我知道编译器会根据目标和调用约定等生成不同的汇编代码,但一般来说,这个本地结构是否必须首先存储在某个地方,以便编译器知道如何在调用函数时将其放入堆栈?提前致谢。

【问题讨论】:

  • 如果您的意思是局部变量已初始化,那么初始化确实必须存储在某个地方(很可能是数据段),除非它非常简单(可能所有字节都为零)。但这就是为什么 C 在调用函数时不将局部(自动)变量设置为预定值的部分原因;处理初始化通常需要时间/空间,无论如何都会被覆盖。
  • 但是它如何知道每次调用时都将结构放在那里、大小、成员的偏移量等?这些信息不是存储在某个地方吗?
  • 是的,它存储在某个地方——我建议它可能是数据部分,但我没有剖析您机器上生成的汇编语言以了解它是如何完成的;事实上,我也没有检查过我的机器)。编译器/链接器的工作是确保它正确发生。该标准没有规定必须如何完成;它只是要求必须达到效果。

标签: c function struct compilation stack


【解决方案1】:

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

如果是局部变量:
写入占位符的“地址”值是相对的,是函数启动时堆栈位置“顶部”的偏移量。
否则,它就像全局占位符的值一样确定。堆栈上的位置受访问变量的影响,可以选择使用 struct 成员的子偏移量。实际地址由堆栈位置(即堆栈指针的值)加上占位符中的相对偏移量确定。

占位符实际上是偏移量列表,与实际的二进制代码一起存储在二进制文件(例如 program.exe)中。类似于“当您决定在内存中的哪个位置找到此变量时,然后将地址写入此处列出的代码中的所有位置:...”。例如,写入这些位置将在一个字节中放入一个有意义的值,在执行期间该值将被解释为相对“MOV”汇编指令的文字偏移量;相对于例如指向 BSS 节开头的节指针。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    相关资源
    最近更新 更多