我可以將常規函式指標傳遞給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);
}
結果是:
非法指令(核心轉儲)
為什么第一個選項很糟糕,而第二個選項沒有?
另外,我可能誤讀了atexit()
https://man7.org/linux/man-pages/man3/atexit.3.html
或
https://pubs.opengroup.org/onlinepubs/007904875/functions/atexit.html上的檔案
但在我看來,那里并沒有提到為什么第二種情況不起作用的資訊。
uj5u.com熱心網友回復:
在另一個函式中定義一個函式是 GCC 擴展。根據GCC 檔案,嵌套函式的生命周期在包含函式的執行結束時結束:
…如果你試圖在包含函式退出后通過它的地址呼叫嵌套函式,一切都會崩潰…
因此,f2
退出后,指向f22
它提供的指標不支持任何進一步使用,并且將其傳遞atexit
給稍后呼叫會導致所有地獄都崩潰。
(實際上,GCC 通過在程式堆疊上創建一些可執行代碼來實作嵌套函式,即使大部分函式代碼像往常一樣在“文本”區域中。指向嵌套函式的指標指向堆疊上的這段代碼。在包含函式退出后,它的堆疊空間通常會被重新用于其他目的,破壞在堆疊上創建的代碼。因此嘗試執行該代碼失敗,因為位元組已更改。)
uj5u.com熱心網友回復:
嘗試f22
在頂層而不是內部定義函式f2
。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/467257.html
下一篇:字典對串列中物件的速度進行分類