如何知道程序中每个变量的地址,指针,函数,函数的返回地址等?

时间:2013-05-21 10:10:17

标签: c memory-address

我想检查代码的每一行的地址。我想知道:

  • 创建变量时,在哪个地址?
  • 创建函数时,在哪个地址?
  • 当一个函数返回时,那么在什么地址?

我在这里想做什么? 使用dumpbin获取信息。

我期待什么?

fun main add:0x0000
var int i add:0x2496
var int j add:0x249A

非常感谢正确解释的适当帮助。

2 个答案:

答案 0 :(得分:5)

你的问题很模糊。您没有提到编译器,处理器或操作系统,这可能会影响这一点。

另请注意,只有全局性的内容(如static变量和函数)才能具有绝对地址。

通常会在堆栈上创建自动变量(“普通”变量),因此在变量在范围内之前不能拥有您可以知道的绝对地址。

代码行当然没有地址,特别是它不必全部是顺序的。例如,典型的C for循环标头是源级别的单行代码:

for(int i = 0; i < n; ++i)

但是它可以生成展开的组件,其中一些组件位于循环体之后,而另一些则之前。

此外,无法保证特定的源代码行生成任何特定数量的机器代码,有些可能会因编译器的优化而消失,当然对于数据声明来说,甚至更少的保证。

答案 1 :(得分:2)

您请求的信息不是编译器生成的目标代码的正常部分,通常无法通过检查目标代码或普通符号表来完全获取。大部分信息不会保留在目标代码中,因为目标代码的目的只是为了能够执行程序。有关目标代码来源的信息(例如创建它的源代码行或源代码中使用的名称)根本不需要执行。

您请求的大部分信息都是在您请求时由编译器生成的调试信息中提供的,就像-g切换到GCC一样。此调试信息以各种格式创建,具体取决于编译器。当然可以自己或使用各种工具检查这些信息,但这样做的意思将详细取决于您使用的编译器和其他工具。这样做很有用,需要对调试信息格式进行大量研究。

可以通过使用调试器(例如gdb)来检查大部分调试信息。调试器通常提供工具来检查与特定源代码行相关的指令或查找为对象分配的内存。

但是,从源代码到执行程序中的指令或数据的映射可能非常复杂。某些源代码行可能已完全消失,因为优化器推断它们是不必要的。举个简单的例子,考虑一下:

b = a;
c = b;
d = c;

我希望c = b;的程序中没有任何指令;我希望编译器只需将a直接移动到d而无需中间步骤,甚至可以根据具体情况进行优化。

此外,在处理对象(例如您的某个变量)时,编译器可能会生成有时在寄存器中具有该对象但在内存中根本没有该对象的代码,并且有时在内存中具有该对象。对象可能部分存在于存储器中,部分存在于寄存器中。 (例如,如果一个对象由八个字节组成,并且编译器耗尽了执行某些工作所需的寄存器空间,它可能会将该对象的四个字节存储到堆栈中,使用新的可用寄存器,并重新加载来自栈。)