我想检查每一行代码的地址。我想知道:
- 创建变量时,在什么地址?
- 创建函数时,在什么地址?
- 当一个函数返回时,在什么地址?
我想在这里做什么?使用 dumpbin 获取信息。
我期待什么?
fun main add:0x0000
var int i add:0x2496
var int j add:0x249A
高度赞赏适当解释的适当帮助。
我想检查每一行代码的地址。我想知道:
我想在这里做什么?使用 dumpbin 获取信息。
我期待什么?
fun main add:0x0000
var int i add:0x2496
var int j add:0x249A
高度赞赏适当解释的适当帮助。
你的问题很模糊。您没有提到编译器、处理器或操作系统,这可能都会影响到这一点。
另请注意,只有本质上是全局的东西(如static
变量和函数)才能具有绝对地址。
自动变量(“普通”变量)通常会在堆栈上创建,因此在变量处于作用域之前没有绝对地址可以知道。
代码行当然没有地址,特别是它不必都是连续的。例如,典型的 Cfor
循环头是源代码级别的单行代码:
for(int i = 0; i < n; ++i)
但它可以生成分散的程序集,其中一些在循环体之后,一些在循环体之前。
此外,不能保证特定的源代码行会生成任何特定数量的机器代码,有些可能会由于编译器的优化而消失,当然对于数据声明,就更没有保证了。
您请求的信息不是编译器生成的目标代码的正常部分,通常无法通过检查目标代码或正常符号表来完全获得。大多数此类信息不会保留在目标代码中,因为目标代码的目的只是使执行程序成为可能。关于目标代码来源的信息(例如创建它的源代码行或源代码中使用的名称)对于执行来说是完全不需要的。
您请求的大部分信息都在您请求时由编译器生成的调试信息中提供,就像-g
切换到 GCC 一样。此调试信息以多种格式创建,具体取决于编译器。当然可以自己或使用各种工具检查这些信息,但这样做的方法将取决于您使用的编译器和其他工具的详细信息。这样做有用需要对调试信息格式进行大量研究。
许多调试信息可以通过使用调试器来检查,例如gdb
. 调试器通常提供工具来检查与特定源代码行关联的指令或查找为对象分配的内存。
但是,从源代码到执行程序中的指令或数据的映射可能非常复杂。一些源代码行可能已经完全消失了,因为优化器推断它们是不必要的。作为一个简单的例子,考虑:
b = a;
c = b;
d = c;
我希望程序中没有任何指令c = b;
;我希望编译器a
直接进入d
而无需干预步骤,它甚至可以根据情况进行优化。
此外,在处理对象(例如您的变量之一)时,编译器可能会生成有时将对象保存在寄存器中而根本不在内存中的代码,有时将对象保存在内存中。一个对象甚至可能部分在内存中,部分在寄存器中。(例如,如果一个对象由 8 个字节组成,而编译器用尽了执行某些工作所需的寄存器空间,它可能会将对象的 4 个字节存储到堆栈中,暂时使用新可用的寄存器,然后从堆。)