为什么我不能将动态函数指针传递给 atexit()?
Why can't I pass a dynamic function pointer to atexit()?
我可以将常规函数指针传递给 atexit()
:
void f1(void)
{
printf("f1\n");
}
int main() {
void (*fun_ptr)(void) = &f1;
atexit(fun_ptr);
}
但是当我传递从另一个函数返回的函数指针时:
typedef void (*f22_t) (void);
f22_t f2(void) {
void f22(void) {
printf("f22\n");
}
return f22;
}
int main() {
void (*fun_ptr2)(void) = f2();
atexit(fun_ptr2);
}
结果是:
Illegal instruction (core dumped)
为什么第一个选项有效而第二个选项无效?
此外,我可能误读了 atexit()
上的文档
https://man7.org/linux/man-pages/man3/atexit.3.html
要么
https://pubs.opengroup.org/onlinepubs/007904875/functions/atexit.html
但在我看来,它没有提到为什么第二种情况不起作用的信息。
在另一个函数中定义一个函数是 GCC 扩展。根据 the GCC documentation,嵌套函数的生命周期在包含函数的执行结束时结束:
… If you try to call the nested function through its address after the containing function exits, all hell breaks loose…
因此,在 f2
退出后,它提供的指向 f22
的指针将不再支持任何进一步的使用,将其传递给 atexit
以供稍后调用会导致所有地狱挣脱束缚。
(实际上,GCC 通过在程序堆栈上创建一些可执行代码来实现嵌套函数,即使大部分函数代码像往常一样位于“文本”区域。嵌套函数的指针指向此堆栈上的代码。在包含函数退出后,其堆栈 space 通常会被重新用于其他目的,从而破坏在堆栈上创建的代码。因此尝试执行该代码失败,因为字节已更改。)
尝试在顶层而不是在 f2
内部定义 f22
函数。
我可以将常规函数指针传递给 atexit()
:
void f1(void)
{
printf("f1\n");
}
int main() {
void (*fun_ptr)(void) = &f1;
atexit(fun_ptr);
}
但是当我传递从另一个函数返回的函数指针时:
typedef void (*f22_t) (void);
f22_t f2(void) {
void f22(void) {
printf("f22\n");
}
return f22;
}
int main() {
void (*fun_ptr2)(void) = f2();
atexit(fun_ptr2);
}
结果是:
Illegal instruction (core dumped)
为什么第一个选项有效而第二个选项无效?
此外,我可能误读了 atexit()
上的文档
https://man7.org/linux/man-pages/man3/atexit.3.html
要么
https://pubs.opengroup.org/onlinepubs/007904875/functions/atexit.html
但在我看来,它没有提到为什么第二种情况不起作用的信息。
在另一个函数中定义一个函数是 GCC 扩展。根据 the GCC documentation,嵌套函数的生命周期在包含函数的执行结束时结束:
… If you try to call the nested function through its address after the containing function exits, all hell breaks loose…
因此,在 f2
退出后,它提供的指向 f22
的指针将不再支持任何进一步的使用,将其传递给 atexit
以供稍后调用会导致所有地狱挣脱束缚。
(实际上,GCC 通过在程序堆栈上创建一些可执行代码来实现嵌套函数,即使大部分函数代码像往常一样位于“文本”区域。嵌套函数的指针指向此堆栈上的代码。在包含函数退出后,其堆栈 space 通常会被重新用于其他目的,从而破坏在堆栈上创建的代码。因此尝试执行该代码失败,因为字节已更改。)
尝试在顶层而不是在 f2
内部定义 f22
函数。