簡體   English   中英

如何在 Visual Studio 2008 C++ 中捕獲被零除錯誤?

[英]How to catch divide-by-zero error in Visual Studio 2008 C++?

如何在 Visual Studio 2008 C++ 中捕獲被零除錯誤(而不是其他錯誤;並且能夠訪問異常信息)?

我試過這個:

try {
  int j=0;
  int i= 1/j;//actually, we call a DLL here, which has divide-by-zero
} catch(std::exception& e){
  printf("%s %s\n", e.what()); 
}  catch(...){
  printf("generic exception");
}

但這適用於通用的 ... catch 塊。 我知道特定於 MS 的 __try 在這里可能很有用,但我更喜歡標准 C++,並且無論如何我都有阻止使用 __try 的析構函數。

澄清:為了討論目的,上面的代碼被簡化了。 實際上,被零除是一個錯誤,它發生在我沒有源代碼的第三方 DLL 深處。 錯誤取決於我傳遞給庫的參數(復雜結構的句柄),但不是以任何明顯的方式。 所以,我希望能夠優雅地恢復。

C++ 本身不會將被零除作為異常處理。

引用 Stroustrup 的話:

“低級事件,例如算術溢出和被零除,假定由專用的低級機制處理,而不是由異常處理。這使 C++ 在算術方面能夠匹配其他語言的行為。它還避免了在大量流水線架構上發生的問題,在這些架構中,諸如除以零之類的事件是異步的。”

“C++ 的設計和演變”(Addison Wesley,1994 年)

在任何情況下,例外情況是從來沒有進行適當的處理的前提條件更換。

要在 Visual C++ try->catch (...) 中捕獲除以零異常,只需在項目設置中啟用 /EHa 選項即可。 請參閱項目屬性 -> C/C++ -> 代碼生成 -> 將 Enable C++ Exceptions 修改為“Yes With SEH Exceptions” 而已!

在此處查看詳細信息: http : //msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

假設您不能簡單地修復異常生成代碼的原因(可能是因為您沒有該特定庫的源代碼,也可能是因為您無法在輸入參數引起問題之前對其進行調整)。

您必須跳過一些障礙才能按照您的意願完成這項工作,但它可以完成。

首先,您需要通過調用_set_se_translator() (參見此處)來安裝結構化異常處理轉換函數,然后您可以檢查在發生 SEH 異常時傳遞的代碼並拋出適當的 C++ 異常。

void CSEHException::Translator::trans_func(
    unsigned int code, 
    EXCEPTION_POINTERS *pPointers)
{
   switch (code)
   {
       case FLT_DIVIDE_BY_ZERO : 
          throw CMyFunkyDivideByZeroException(code, pPointers);
       break;
   }

   // general C++ SEH exception for things we don't need to handle separately....
   throw CSEHException(code, pPointers);
}

然后你可以簡單地在 C++ 中以正常方式捕獲你的CMyFunkyDivideByZeroException()

請注意,您需要在要轉換異常的每個線程上安裝異常轉換功能。

您可以使用結構化異常處理(使用 __try 等),也可以安裝結構化異常處理程序轉換器: _set_se_translator

這兩者都是特定於操作系統的。

您不能使用標准 C++ 做到這一點,因為它不是標准 C++ 異常。 這是一個結構化的例外。 對於標准的 C++ 異常,必須有人throw exception; 從代碼。

為什么不先檢查一下? 與用於異常處理的上下文切換相比,簡單j == 0的性能將是微不足道的。

試試下面的代碼:

try
{ 
  const int j=0;
  if (j == 0) { throw std::exception("j was 0"); } 
  const int i= 1/j;    
}
catch(std::exception& e)
{ 
  printf("%s %s\n", e.what());  
}
catch(...)
{ 
  printf("generic exception"); 
}

當然,如果你可以毫無例外地這樣做,你可以這樣做:

const int j = 0;
if (j == 0)
{
  /* do something about the bad pre-condition here */
}
else
{
  const int i = 1 / j;
}

為回應澄清而進行編輯:您必須弄清楚您將哪些輸入交給第三方,導致它們事先被零除,並在調用它們的函數之前處理它。

一個好的方法是使用安全的面向對象的包裝器,如SafeInt 似乎集成在 Visual Studio 2010 中。

更新:
如果被零除發生在第三方代碼中,您唯一的選擇是 SEH 或Seb Rose 回答的等效內容

您可以使用try-except Statement 但是,不要忘記您需要為每個線程設置它。

暫無
暫無

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

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