gpt4 book ai didi

c - 直接访问函数栈

转载 作者:太空宇宙 更新时间:2023-11-04 02:51:06 25 4
gpt4 key购买 nike

我之前问过a question关于采用未指定数量参数的 C 函数,例如void foo() {/* code here */} 并且可以用未指定数量的未指定类型的参数调用。

当我询问像 void foo() {/* code here */} 这样的函数是否有可能获取调用它的参数时,例如foo(42, "random") 有人说:

The only you can do is to use the calling conventions and knowledge of the architecture you are running at and get parameters directly from the stack. source

我的问题是:

如果我有这个功能

void foo()
{
// get the parameters here
};

我称之为:foo("dummy1", "dummy2") 是否可以直接从堆栈中获取 foo 函数中的 2 个参数?

如果是,怎么办?是否可以访问完整堆栈?例如,如果我递归调用一个函数,是否可以以某种方式访问​​每个函数状态?

如果不是,那么参数数量未指定的函数有什么意义?这是 C 编程语言中的错误吗?在哪些情况下,任何人都希望 foo("dummy1", "dummy2") 编译并正常运行 header 为 void foo() 的函数?

最佳答案

很多“如果”:

  1. 您坚持使用一个版本的编译器。
  2. 一组编译器选项。
  3. 设法说服您的编译器永远不会在寄存器中传递参数。
  4. 说服您的编译器不要将对同一个函数使用不同参数的两个调用 f(5, "foo") 和 f(&i, 3.14) 视为错误。 (例如,这曾经是早期 DeSmet C 编译器的一项功能)。

然后函数的激活记录是可预测的(即你查看生成的程序集并假设它总是相同的):返回地址将在某处和保存的 bp(基指针,如果你的体系结构有一个), 并且参数的顺序将是相同的。那么你怎么知道传递了哪些实际参数呢?您将必须对它们进行编码(它们的大小、偏移量),大概是在第一个参数中,类似于 printf 所做的。

递归(即处于递归调用中没有区别)每个实例都有其激活记录(我说过你必须说服你的编译器永远不会优化尾调用吗?),但在 C 中,与在 Pascal 中不同,你不需要因为没有嵌套的函数声明,所以有一个向后链接到调用者的激活记录(即局部变量)。访问完整堆栈(即当前实例之前的所有激活记录)非常繁琐、容易出错,并且最受想要操纵返回地址的恶意代码编写者感兴趣。

因此,有很多麻烦和假设基本上是徒劳的。

关于c - 直接访问函数栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22126729/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com