簡體   English   中英

如何處理 C++ 中的運行時錯誤?

[英]How to handle runtime errors in C++?

所以,我對 C++ 有點陌生,我想知道什么是好的做法,甚至在編程時如何處理運行時錯誤,這里有一個例子:

State s_toState(std::string state){
  if (state == "MG")
    return State::MG;
  else if (state == "PR")
    return State::PR;
  else if (state == "SP")
    return State::SP;
  else if (state == "SC")
    return State::SC;
  else if (state == "RJ")
    return State::RJ;
  else if (state == "RN")
    return State::RN;
  else if (state == "RS")
    return State::RS;

  // ???
}

所以我有這個 function 將string轉換為State 在不使用異常的情況下,我斷言給定的 state 是現有的(MG、PR、SP 等)的理想方法是什么?

舉個例子,但我要求的是一般規則。 據我所知,我可以使用異常、斷言或只打印錯誤。 我也假裝對此進行單元測試(也是單元測試的新手,對此一無所知)。

這看起來是一個使用異常的好機會。 cplusplus.com 指南是合理的,但我發現玩弄它是一種更好的學習方式。

基本思想是這樣的:

  • function throw異常,終止 function 並將異常傳遞給調用 function 的任何人。
  • 如果調用者在try塊中調用了 function,那么接下來的catch就會被執行。
  • 如果調用者沒有try / catch系統,則調用者也會被終止,並且該過程會重復 function 調用堆棧,直到找到try / catchmain()終止。

答案取決於s_toState “承諾”要做什么。

如果state無效是 function 或其他內部邏輯錯誤的程序員的錯誤。 添加assert並記錄 state 有效性作為前提條件(與指針的!=nullptr相同)。 對於發布版本,添加一些默認行為,這樣程序就不會在可能的情況下崩潰。 或者如果你不寫關鍵的軟件就讓它崩潰,它至少會使調試更容易。

如果它是用戶的可恢復錯誤和合理的場景(不是錯誤),則考慮返回std::optionalthrow 當拋出的異常總是被直接調用者捕獲時,我更喜歡前者,即從不向上傳播調用堆棧。 我也發現它更清楚,因為它強制調用者明確處理它。

對於不可恢復的錯誤,即當直接調用者無法處理nullopt時,只需拋出並讓其他代碼處理即可。

我喜歡try_parse返回std::optional的命名約定,同時parse拋出。

嘗試一下異常和錯誤處理常見問題解答可能是值得的。

一般來說,處理此類錯誤(如任何錯誤)的方式取決於整個程序的需求 - 而您尚未指定。 所以沒有一刀切的“一般規則”。

有選擇和權衡。

一種選擇是為您的State枚舉類型提供表示未確定或無效 state 的枚舉器值,例如

 enum class State {MG, PR, Undetermined};

然后,在您的 function 中,返回未確定的值,例如

State s_toState(const std::string &state)
{
    State return_value = State::Undetermined;
    if (state == "MG")
       return_value = State::MG;
    else if (state == "PR")
       return_value = State::PR;
    // etc

    return return_value;
}

使用這種方法, function 始終返回State類型的有效值。 如果錯誤條件不是很嚴重(即如果提供了無效字符串,程序可以繼續),那么調用者可以決定是否需要檢查返回值。 可以報告多種類型的錯誤條件(例如,通過具有表示不同錯誤的多個枚舉值)不利的一面是調用者可能忘記檢查返回值並且行為不正確。

另一種選擇是拋出異常,例如;

State s_toState(const std::string &state)
{
    if (state == "MG")
       return State::MG;
    else if (state == "PR")
       return State::PR;
    // etc

    throw std::invalid_argument("Bad input string");
}

這個選項需要對拋出什么類型的異常做出明智的選擇(例如,需要傳達關於錯誤狀態的什么信息)。 如果提供了錯誤的字符串,調用者(或整個程序)無法合理地繼續,則此方法可能更可取,因為通過拋出異常,調用者被迫捕獲並采取任何恢復操作以避免被終止。 因此,這種方法可能不適用於非關鍵錯誤——例如,如果提供了錯誤的字符串,則可以合理地繼續執行。

另一種選擇(C++17 及更高版本)是返回std::optional<State> 這允許調用者檢查是否發生了錯誤(例如std::option::has_value() return false ),或者,如果在沒有檢查的情況下訪問該值,則導致拋出std::bad_optional_access類型的異常(其中可能適合呼叫者,或者可能不提供信息)。

也可以使用assert() - 如果指定的條件不正確,它會強制終止。 通常,我更喜歡使用assert()拋出異常,但您可能更喜歡其他方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM