【发布时间】:2016-05-07 10:05:23
【问题描述】:
我有一个void(*)(void) 函数指针,指向一个实际上是void f(int) 的函数。关键是,我现在还不知道它是一个什么样的函数,所以我不能简单地将它转换为void(*)(int)。我想我可以简单地使用函数的参数来准备堆栈。
#include <stdio.h>
void func(int x) {
printf("%p : %d\n", &x, x);
}
int main(int argc, char* argv[]) {
int* ptr = &argc - 8;
*ptr = -1;
printf("%p : %d\n", ptr, *ptr);
void (*f)(void) = (void(*)(void)) &func;
f();
return 0;
}
这会返回:
0x7ffd72ec204c : -1
0x7ffd72ec204c : 0
我希望这会返回 -1 两次。但是,似乎 gcc 在调用函数时添加了一些代码来清除堆栈,这就是为什么func() 显示0 的原因。
是否有某种编译器标志可以用来禁用它?
我正在使用gcc (Debian 4.9.2-10) 4.9.2,但如果我可以让它在任何编译器中工作就足够了!我的名字是Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u3 (2016-01-17) x86_64 GNU/Linux。
我读过关于MUST_PASS_IN_STACK 的文章——这有帮助吗?如果是,我该如何使用它?
我知道这不是特别好的做法。这只是一个理论练习。
【问题讨论】:
-
您假设参数是在堆栈上传递的。他们不必是:)
-
@KubaOber 嗯,有趣,但这就是为什么我也打印地址 - 因为地址是相同的,参数不应该在堆栈上传递吗?如果没有,它们还能在哪里通过?
-
@CamilStaps:在寄存器中。您可能想在修改
&argc - 8之前尝试创建f变量,因为这会将一个新变量推入堆栈,并且可能会弄乱您编写的内容。但请注意,这都是未定义的行为,编译器可以随意破坏您的程序。 -
@Cornstalks 好吧,这是有道理的 - 有没有办法通过编译器标志或在
main函数中禁用它? -
哪个系统,哪个编译器?这是未定义的行为,但您可能会在某些系统上使其正常工作。
标签: c gcc stack function-pointers compiler-flags