C 有没有办法知道全局变量和静态变量在数据段(.data+;.bss)中的位置?

C 有没有办法知道全局变量和静态变量在数据段(.data+;.bss)中的位置?,c,memory,assembly,x86,portable-executable,C,Memory,Assembly,X86,Portable Executable,我想将所有全局变量和静态变量转储到一个文件中,并在下一次程序调用时重新加载它们。我想到的一个解决方案是将.data段转储到一个文件中。但是,32位机器上的数据段跨越2^32地址空间(4GB)。变量位于地址空间的哪一部分?如何知道应该转储.data段的哪一部分 当加载转储文件时,我猜由于变量在数据段中由偏移量引用,所以将整个转储文件memcpy到所谓的“变量区域”的起点是安全的。如果我错了,请纠正我 编辑 一个好的开始是。我不认为可以保证每次执行都会有sam变量序列,因此偏移量可能指向错误的内容。

我想将所有全局变量和静态变量转储到一个文件中,并在下一次程序调用时重新加载它们。我想到的一个解决方案是将.data段转储到一个文件中。但是,32位机器上的数据段跨越2^32地址空间(4GB)。变量位于地址空间的哪一部分?如何知道应该转储.data段的哪一部分

当加载转储文件时,我猜由于变量在数据段中由偏移量引用,所以将整个转储文件memcpy到所谓的“变量区域”的起点是安全的。如果我错了,请纠正我

编辑


一个好的开始是。

我不认为可以保证每次执行都会有sam变量序列,因此偏移量可能指向错误的内容。

您的问题是如何找到数据段的开始和结束。我不知道怎么做,但我可以给你一些想法

如果您的所有数据都是相对独立的(它们是在同一个模块中声明的,而不是在单独的模块中声明的),那么您可以在某种结构中声明它们,因此开头是结构的地址,结尾是您将在结构之后声明的某个变量。如果我记得清楚的话,MASM有一个“RECORD”指令或类似的东西,可以用来将变量分组在一起

或者,您可以声明另外两个模块,一个带有名为“开始”的变量,另一个带有名为“结束”的变量,并确保第一个模块在其他模块之前链接,第二个模块在其他模块之后链接。这样,这些变量实际上可能会标记数据段的开始和结束。但我不确定这一点,我只是给你一个指针


需要记住的一点是,您的数据将不可避免地包含指针,因此只有当您运行的操作系统能够保证您的程序始终加载在同一地址时,保存和加载所有数据才会起作用。如果没有,那就忘了它。但是如果你能得到这个保证,那么是的,加载数据应该是可行的。您甚至不需要memcpy,只需将读取操作的缓冲区设置为数据段的开头。

整个程序的状态可能非常复杂,不仅涉及变量,还涉及寄存器中的值。几乎可以肯定的是,您最好跟踪要存储的数据,然后自己将其存储到文件中。通过正确的设置和封装,这可以相对轻松。然后,当您恢复应用程序时,读取程序状态并继续。

假设您正在使用gnu工具(gcc、binutils),如果您查看嵌入式人员使用的链接器脚本,就像gba开发人员和使用ROM的微控制器开发人员(例如yagarto或devkit arm)。在链接器脚本中,它们用变量围绕感兴趣的片段,这些变量可以在代码中的其他地方使用。例如,对于基于rom的软件,在链接器脚本中指定数据段的ram位于rom或rom位于ram,意思是链接,就像数据段位于该地址空间的ram中一样,但也将数据本身链接到该地址空间的rom中一样,引导代码然后使用这些变量将.data段从rom复制到ram。我不明白为什么你不能做同样的事情,让编译器/链接器工具告诉你东西在哪里,然后运行时使用这些变量从内存中获取数据并将其保存到hybernate或关闭,然后从任何地方恢复数据。当然,用于执行还原的变量不应是.data段的一部分,否则您将丢弃用于还原该段的变量。

在Windows上,可以从内存中的PE标头获取数据和bss段的位置和大小。本规范中记录了其布局方式和解析方式:


你为什么要这样做?@Paul R:看不出这个问题怎么会重复你所指的问题。@DanFego:需要用当前状态“冻结”一个长时间运行的程序,然后再继续运行。可能重复的@drhirsch:不会称之为重复,在大量阅读之后,这是一个后续问题。一旦程序被编译,变量序列如何变化?变量只是内存中的偏移量,偏移量是在编译时设置的。只有当程序被编译并链接为位置独立(PIC)时才是这样。通常,加载程序时,所有地址都会重新定位到加载程序的位置。这不一定在每个方面都是一样的start@drhirsch:我在哪里可以进一步了解它?具体地说,关于程序加载时地址的重新定位。@drhirsch我的答案的最后一段在这方面更为切题。变量将始终处于相同的序列中。他们的位置只会改变。所以,只有当它们包含指针时才会出现问题。谢谢,但这并不能回答我的问题。我非常了解你建议的解决方案,如果没有其他选择,我会选择。但是我有太多的变量要携带,现在我试图避免它。指针上的注释是一个很好的注释!没有想到这一点,这可能会使“转储”的想法变得不可行。对于.bss,也一样,只需确保用于执行还原的变量/代码不在这两个段中,例如使用本地、非静态变量。