[英]Call to a [[noreturn]] function and order of destruction
考慮到以下代碼,我,或者更確切地說是原始代碼的開發人員,預計函數本地 object 將在調用 [[noreturn]] fubar()
function 之前被破壞。
#include <iostream>
#include <iostream>
using std::cout;
using std::endl;
class Static
{
public:
Static() { cout << "Static::Static" << endl; }
~Static() { cout << "Static::~" << endl; }
};
class Automatic
{
public:
Automatic() { cout << "Automatic::Automatic" << endl; }
~Automatic() { cout << "Automatic::~" << endl; }
};
[[noreturn]] void fubar() {
cout << "It's FUBAR" << endl;
throw 42;
}
void foo() {
Automatic a;
static Static b;
fubar();
cout << "It's fine." << endl;
}
int main()
{
try {
foo();
}
catch(int a)
{
cout << "main() was FUBARed. Answer is " << a << endl;
}
return 0;
}
顯然這不是真的。 例如 output 用 GCC 10 編譯后顯示Automatic
在進入fubar
后被破壞,但它發生在捕獲異常之前。 這與 fubar() 不是noreturn
的行為完全相同。
Automatic::Automatic
Static::Static
It's FUBAR
Automatic::~
main() was FUBARed. Answer is 42
Static::~
這是一種定義的行為嗎? 這是異常處理堆棧展開的結果。 進一步調查表明exit(0);
(它本身被聲明為[[noreturn]]
)。
[[noreturn]] void fubar() {
cout << "It's FUBAR" << endl;
exit(0);
}
導致自動裝置的不完全破壞:
Automatic::Automatic
Static::Static
It's FUBAR
Static::~
這實際上是否意味着對聲明為 [[noreturn]] 的 標准函數的調用對於在進程執行后不進行清理的操作系統來說是一個很大的“不”,並且使用局部變量來初始化任何操作系統范圍的資源如果任何這樣的調用是可能的(不會發生適當的取消初始化)或者我發現一個缺陷是不安全的?
這與
fubar()
不是noreturn
的行為完全相同。
正如預期的那樣; [[noreturn]]
在這里是一個紅鯡魚,因為fubar()
不返回(因此滿足該屬性旨在發出信號的要求)。
從[dcl.attr.noreturn]/2和[dcl.attr.noreturn]/3 [強調我的]:
/2如果調用 function
f
之前使用noreturn
屬性聲明f
並且f
最終返回,則行為未定義。 [注意: function可能會通過拋出異常終止。 ——尾注]/3推薦做法:如果標記為
[[noreturn]]
的 function 可能返回,則實現應發出警告。
[[noreturn]]
屬性僅對在某些執行路徑中返回的函數至關重要(這是編譯器可能幫助標記的錯誤); 即注釋為[[noreturn]]
的 function 實際上確實返回導致未定義的行為,建議編譯器將包含返回程序路徑的程序標記為帶有警告的[[noreturn]]
注釋函數。
[[noreturn]]
屬性主要是為了避免在非空 function 中出現關於缺少返回的警告。
它們是 function 到“noreturn”的幾種方式:
std::terminate
/ exit
/ abort
,...)。您必須閱讀有關您調用的“noreturn”function 的文檔以了解其行為。 [[noreturn]]
將標記為此類的 std 函數與其清理行為聯系起來。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.