C 在一个函数中,是否可以获得由返回值初始化的变量的内存地址?

C 在一个函数中,是否可以获得由返回值初始化的变量的内存地址?,c,return-value,inline-assembly,calling-convention,C,Return Value,Inline Assembly,Calling Convention,我一直在研究C语言中的内联汇编以及调用堆栈是如何工作的,但我无法确定是否可以从函数中检索请求函数返回值的变量的地址 int假设函数(){ /*... …某个程序集从调用堆栈中获取“int a”的地址? ...*/ 返回5; } int main(){ int a=假设的函数(); } 这可能吗?否。int在寄存器中返回,被调用方不参与调用方在返回后对该寄存器所做的操作。它可能永远不会存储在内存中 如果返回类型不是int,而是某个足够大的值,使得调用约定按值返回它,那么假设的_func将有一个输

我一直在研究C语言中的内联汇编以及调用堆栈是如何工作的,但我无法确定是否可以从函数中检索请求函数返回值的变量的地址

int假设函数(){
/*...
…某个程序集从调用堆栈中获取“int a”的地址?
...*/
返回5;
}
int main(){
int a=假设的函数();
}

这可能吗?

否。
int
在寄存器中返回,被调用方不参与调用方在返回后对该寄存器所做的操作。它可能永远不会存储在内存中

如果返回类型不是
int
,而是某个足够大的值,使得调用约定按值返回它,那么
假设的_func
将有一个输出地址。(或者一个假设的(糟糕的)调用约定可能会通过隐藏指针而不是寄存器返回int。假设该机器与所有实际CPU一样是寄存器机器。)

但这可能只是一个临时返回值,而不是赋值的实际LHS。(或者初始化,如果不是C++,它与C中的相同内容非常接近)。特别是当任务分配给全局或其他对象时。有关
*out=foo()的情况,请参见
其中
T*out
是一个函数arg。证明将该函数arg作为
foo()
的返回值对象传递是否/何时安全非常重要

有些编译器甚至不尝试优化,只是在堆栈上为返回值临时留出空间,然后从那里复制到最终对象中

正如@prl所指出的,返回值甚至可能不是变量的初始值设定项。e、 g.
printf(“%d\n”,foo())只是将返回值传递给函数arg
foo()丢弃返回值,不在任何位置分配它。(但如果调用约定指定函数通过隐藏指针返回,则调用方必须将指针传递到足够的暂存空间。被调用方仍将写入其返回值,并且不需要将错误从错误指针中分离出来或覆盖其他内容。这是与C操作不同的asm/调用约定细节或者我猜你可以说返回值对象仍然存在,只是没有分配到任何地方。)


加上使用内联汇编,您甚至无法访问该程序集。除非您将编写
\uuuuuu属性(裸体))计算在内
函数,您仍然在asm语句中编写整个函数,编译器只处理函数名的名称混乱。没有序言或尾声,也没有用C变量为args抽象出调用约定,并且
返回一个
。(/抱怨C编译器不能像手工编写的asm那样创建在多个寄存器中返回多个单独值的函数。)


但是,即使使用手写asm,对于x86和ARM等普通ISA上的正常调用约定,也无法做到这一点。int的返回值对象只是一个寄存器。

这在任何实际意义上都是不可能的。返回值可能没有分配给变量,如果是,变量可能没有内存地址。即使这两种情况都不存在,并且返回值被分配给内存中的变量,该变量的地址也不可用于函数


一种不切实际的方法来解决这个问题(例如,如果调试需要)是从堆栈中获取返回地址,并反汇编指令,查找将返回值寄存器写入内存的指令。这样的指令(如果存在)通常位于返回点后的几个指令内。

if
int a=if\u func();
在另一个函数中,它应该位于该函数的stackframe上,因此使用它可以找到该函数stackframe并定位该变量

有关更多特别信息:

No.:)。对不起,这是一个简单的答案。唯一的方法是编写代码,分析内存中的二进制文件,并确定在调用返回后其返回值最终被分配的位置。谁说该变量甚至有内存地址?哦,好的:(我确实找到了一些代码,可以在内存中查找该帧指针,但我打赌这需要很长时间,而且还有很多代码我几乎不懂。任何人都想以“否”作为官方答案?XD如果您是以编程方式执行此操作,您可能会查看GNU C
\u内置返回地址(0)
获取您自己的返回地址(即跳到函数的
调用之后的指令,如果忽略优化的尾调用或假装它们是最终调用方。)假设int a在main()中,并根据其他答案,如果它首先声明并未初始化,然后使用函数分配一个值,是否可以在main上执行回溯以查找某个地址?@TiboroJacko:No,不需要人工反向工程。或者在调试构建中(即使局部变量也有地址),也许您也可以解析调试符号。但是使用调试符号的障碍是您必须已经知道变量名
a
;您的函数不知道这一点。