我一直在研究C语言中的内联汇编以及调用堆栈的工作方式,但是我一直无法弄清是否有可能从中检索请求函数返回值的变量的地址。在函数内。
int hypothetical_func(){
/*...
.. some assembly to get the address of 'int a' from the call stack?
...*/
return 5;
}
int main(){
int a = hypothetical_func();
}
这有可能吗?
NO
如果返回类型不是int
,而是足够大以至于调用约定按值返回了它,则hypothetical_func
将具有用于输出的地址。 (或者假想的(可怕的)调用约定可能甚至通过隐藏指针而不是寄存器返回int
。假设该计算机是与所有实际CPU一样的寄存器计算机。)
但是那可能只是返回值的临时值,而不是赋值的实际LHS。特别是如果赋值是全局变量或某物。有关What prevents the usage of a function argument as hidden pointer?的情况,请参见*out = foo();
,其中T *out
是函数arg。证明是否/何时可以安全地将函数arg作为foo()
的返回值对象传递是非常重要的。
而且有些编译器甚至没有尝试优化,只是在堆栈上为返回值临时保留空间,然后从那里复制到最终对象中。
加上inline
程序集,您甚至无法访问该程序。除非算上要编写__attribute__((naked))
函数,否则您仍要在asm语句中编写整个函数,并且编译器除了处理函数名称的名称处理之外不会处理其他任何事情。无序或结尾。但是即使使用手写的asm,也无法对x86和ARM等普通ISA上的常规调用约定执行此操作。 int
的返回值对象只是一个寄存器。
从任何实际意义上讲都是不可能的。返回值可能未分配给变量,如果是,则该变量可能没有内存地址。即使这两种情况都不是,并且返回值已分配给内存中的变量,该变量的地址也无法用于该函数。
一些概念:
如果int a = hypothetical_func();
在另一个函数内部,则它应该在该函数的堆栈框架中,因此,使用backtrace()
您可以找到该函数的堆栈框架并找到该变量。