[英]How to catch run time error in C and C++?
就像修改CONST int
一樣,
我可以注冊一個特定的 function 來處理運行時錯誤,這樣這種操作就會失敗而不是終止應用程序嗎?
如果您的意思是 C++,則有一個名為runtime_error
的異常 class 。 您可以使用 catch 子句捕獲它:
catch(std::runtime_error& e) {}
但是,C 和 C++ 中的許多事情(例如修改 const int)會導致未定義的行為。 您無法在運行時捕獲它們。 您無法捕獲它們,因為沒有拋出異常(從技術上講,任何事情都可能發生,包括拋出異常(僅限 C++),但這不是您可以或不應該希望的)。
解決方案是編寫干凈安全的代碼。 為此,許多書中列出了許多建議。 :)
根據規范,修改const
是“未定義的行為”,因此編譯器可以做任何事情。 在實踐中,許多實現有時會為此類代碼生成運行時錯誤,但很多不會。 它通常取決於程序的性質。 這是一個插圖:
#include <stdio.h>
#include <string.h>
typedef int (*fn)(const char *);
extern const fn global_fn_ptr;
extern const char global_string[];
const fn global_fn_ptr = puts;
const char global_string[] = "hello";
int main(int argc, char *argv[])
{
puts("Setting global_fn_ptr to NULL");
*(fn *)&global_fn_ptr = NULL;
puts("Setting string to \"bye\"");
strcpy((char *)global_string, "bye");
return 0;
}
在我的系統上,我通過修改字符串獲得了 SIGBUS,但修改 function 工作正常。 這是由於 function 指針的特殊性質,其值並不總是在運行時確定,因此該值必須存儲在可寫的 memory 中。
在 C++ 中捕獲 SIGBUS 或 SIGSEGV 並將其轉換為異常通常是不安全的。 從信號處理程序中正確地longjmp
也是非常困難的——在 C 中使用這種模式的代碼中有一半可能是不正確的。 最安全的選擇是讓程序立即終止,或者如果您真的需要運行時的這種幫助,請非常小心地使用 C 代碼,以便您可以在非本地退出中釋放適當的資源 - C++ 不會這樣做,因為longjmp
贏了不要調用析構函數。
或者您可以直接轉到 C# 或 Java,它們都有為您執行此操作的運行時以及之后清理的垃圾收集器。
這是特定於操作系統的。 語言本身將這些指定為未定義的行為。
在與 POSIX 兼容的操作系統中,您的程序可以在 memory 訪問受限的情況下捕獲SIGSEGV
信號,在無效指令的情況下捕獲SIGILL
信號,在非法浮點運算(例如被零除)的情況下捕獲SIGFPE
。
在 C 中,運行時錯誤通常會生成可由信號處理程序處理的信號。
在 C++ 中,運行時錯誤也可以作為可以在 try/catch 塊中捕獲的異常拋出。
要在某個時刻繼續而不是崩潰,您需要在信號處理程序中使用 setjmp/longjmp - 從程序錯誤中捕獲信號后返回是不安全的
我大錯特錯。
嘗試修改 const 限定的變量確實是未定義的行為,而且似乎已經有好幾年了。 它可能會也可能不會產生運行時錯誤; 能不能用得看平台。
正如@Dietrich Epp 耐心指出的那樣,n1570 是 C 標准下一次迭代的委員會草案,在第 6.7.3 節中給出了規則。 自 C89 以來,該部分的措辭可能沒有改變。
我非常抱歉以其他方式提出索賠; 以及侮辱這個群體的成員。 尤其是迪特里希。
現在,我在哪里可以找到一些美味的散養烏鴉?
您必須知道這一點,並且一定是您的示例考慮不當,但是無論如何都值得注意,以防有人誤解:
在 C 中,在運行時沒有const int
(或const
其他任何東西)這樣的東西; const
純粹是一個編譯時概念。 因此,修改const int
沒有運行時錯誤。
如果我理解正確,您所談論的場景是(通常)根據語言未定義的場景。
這些情況會導致不可預知的結果,正如您所指出的,這些結果有時可能包括程序繼續運行並看起來“工作”,或者它可能會崩潰,或者鼻惡魔可能會自發地出現。
如果您想捕捉未定義行為的使用,那么您可以在某些情況下使用工具來執行此操作。
例如, Electric Fence非常擅長揭示您不應該寫入 memory 的位置(盡管不要在發布版本中激活它。)。 這是否適用於寫入您拋棄的const
的東西將取決於應用了哪些優化; object可能具有可寫的 memory,並且在物理上無法確定您實際上做錯了什么。
你不會得到一個整潔的語言層異常。 由於無論如何您都將不得不在工具路線上使用 go,因此只需盡可能應用 static 和動態分析工具並配置文件。 沒有萬無一失的方法可以突然打開“理智地通知我所有未定義行為的使用”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.