C在另一个嵌套函数内调用嵌套函数



当我在另一个嵌套函数中调用trampoline嵌套函数时,trampoline嵌套函数无法访问trampoline变量,在本例中是浮点数r

typedef void (*callback)();
callback Wrapper(float r) {
auto void foo();
void foo() {
// do something with r.
}
return &foo;
}
int main(void)
{
callback c = Wrapper(0.1);

auto void foo2();
void foo2() {
c(); // doesn't work unless i don't use r in foo (Segmentation fault (core dumped))
}
foo2();
c(); // works fine.
return 0;
}

来自gcc文档的嵌套函数:

如果你试图在包含函数的函数退出后通过它的地址调用嵌套函数,那么一切都将变得一团糟。

函数void foo在函数Wrapper内部定义,函数foo的地址从Wrapper返回。然后在函数Wrapper退出后调用该函数。正如文档中所述,你的代码使"乱成一团"。

可以把嵌套函数看作是在堆栈上分配的变量。当函数返回时,嵌套函数停止存在。

trampoline嵌套函数不能访问trampoline变量,在本例中是浮点r。

变量r仅在Wrapper函数内具有作用域。一旦Wrapper退出,变量r将不再存在。

auto void foo();
auto void foo2();

这是奇怪的。没必要写这个。只需编写函数-它就像默认的auto

一旦Wrapper()完成,您就不能使用c(),因为它超出了范围。想象一下,如果这个函数只在Wrapper()执行时存在(即使你知道它的代码仍然在某个地方,你不能执行它,原因如下所述,如果它不是从包含它的函数的内部),你在main()的开头调用Wrapper(),Wrapper()返回一个指向Wrapper()局部函数的指针。好吧,这个指针是一个假指针,因为当程序从Wrapper返回时,函数就已经不存在了。这就像返回一个指向局部变量的指针。

我应该说未定义行为,但是当我们谈论GCC扩展时,该术语也超出了范围,所以我能说什么呢?(正如我从KamilCuk的另一个答案中看到的,GNU使用这个术语,这对我来说听起来很完美)

嵌套函数的实现意味着使用显示(指向所有嵌套函数中最近的活动调用记录的指针数组,这是在其他语言中完成的,如Pascal, Ada或Modula-2)来访问外部函数中的作用域标识符,就像您从c()访问float r一样,但后来,当Wrapper没有被执行时,Wrapper()中的局部变量没有显示,对c()的调用出错,因为对1.0的访问很久以前就结束了。

对于所有的目的,你的技巧,试图调用c()范围外(Wrapper()之外)是非法的,我不知道为什么你可以要求这个,但你是错误的,如果你认为你可以维护一个本地资源(如参数rWrapper,调用后使用它的函数返回)

我建议你看看嵌套函数指针的数组,以及编译器如何通过显示访问外部函数上的变量,通过查看嵌套函数的汇编代码(你可以无限地嵌套,并且在每一层嵌套中添加一个指向向量的指针)在标准C中没有显示,因为所有的函数都是在顶层定义的。

最新更新