我了解全局数据将存储在 .BSS 或 .data 段中。
如果我有数据,例如在函数内部定义的结构,则该结构只会在调用函数时才会放置在堆栈上。
编译器在启动时在调用函数之前将这些数据存储在哪里? 我知道编译器根据目标和调用约定等生成不同的汇编代码,但一般来说,这个本地结构是否必须首先存储在某个地方,以便编译器知道在调用函数时如何将其放入堆栈中?提前致谢。
最佳答案
如果是全局变量(也是静态局部变量):
编译器将全局变量作为具有特定地址和大小的内存部分来访问。地址最初是一个占位符(很像变量的名称)。大小是隐式的,具体取决于编译器在汇编/机器代码中选择的访问类型。链接器/加载器知道大小,它确保下一个变量不重叠。
地址占位符在链接(例如嵌入、静态、就地执行)或加载(例如 PC 上的程序、应用程序)期间被替换。
如果是局部变量:
写入占位符的“地址”值是相对的,是启动函数时堆栈位置“顶部”的偏移量。
它的其他确定方式与全局占位符的值类似。堆栈上的位置受到访问变量的影响,可以选择使用结构成员的子偏移量。实际地址由堆栈位置(即堆栈指针的值)加上占位符中找到的相对偏移量确定。
占位符实际上是偏移量列表,与实际的二进制代码一起存储在二进制文件(例如program.exe)中。就像“当您决定在内存中找到该变量时,然后将地址写入此处列出的代码中的所有位置:...”。例如,写入这些位置将在一个字节中放入一个有意义的值,该值在执行期间将被解释为相对“MOV”汇编器指令的文字偏移量;相对于例如指向 BSS 部分开始的部分指针。
简而言之,地址信息位于占位符列表中。这些列表可能根本在内存中找不到,或者在执行时找不到。一旦程序加载(包括填充占位符),就不再需要这些列表。
大小信息是代码的一部分(例如使用 8 位访问或 32 位访问),并且是变量位置布局的一部分。每个变量都在前一个变量后面足够远的地方被访问。
因此,更短地说,您正在查找的信息在执行过程中一半是隐藏的,一半根本不在内存中。
我认为您的问题不是关于变量内部的值。只是为了覆盖它:该值被初始化为 0,一个恒定的初始化值,或者,特殊情况下,根本不初始化,在启动时保留内存中的任何内容。初始化值可以在基本上是常量列表的部分中找到。确切地找到给定变量的常量的位置与占位符类似。
对于局部变量,编译器通常不会初始化,但可以配置为写入 0(这有点“昂贵”)。这就是为什么在使用变量之前初始化变量是一个好习惯。具有显式初始化的局部变量当然是在堆栈帧设置期间初始化的。
关于c - 启动时存储的函数内部定义的本地数据在哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43270183/