Frage

Wie kann ich in Visual Studio 2008 C ++ einen Fehler von Divide-by-Null (und nicht in anderen Fehlern; und in der Lage sein, Ausnahmeinformationen zugreifen zu können)?

Ich habe das versucht:

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");
}

Aber das geht zum generischen ... Fangblock. Ich verstehe, dass das MS-spezifische __try hier irgendwie nützlich sein mag, aber ich würde Standard C ++ bevorzugen, und auf jeden Fall habe ich Destruktoren, die die Verwendung von __try verhindern.

Klärung: Der obige Code ist zu Diskussionszwecken vereinfacht. Tatsächlich ist die Divide-by-Null ein Fehler, der tief in einer DLL von Drittanbietern auftritt, für die ich nicht den Quellcode habe. Der Fehler hängt vom Parameter (ein Handle zu einer komplexen Struktur) ab, die ich in die Bibliothek übergehe, aber in keiner offensichtlichen Weise. Also möchte ich mich anmutig erholen können.

War es hilfreich?

Lösung

Unter der Annahme, dass Sie die Ursache des Ausnahme -Codes nicht einfach beheben können (möglicherweise, weil Sie den Quellcode nicht für diese bestimmte Bibliothek haben und möglicherweise die Eingabeparameter nicht anpassen können, bevor sie ein Problem verursachen).

Sie müssen durch einige Reifen springen, um diese Arbeit zu machen, wie Sie möchten, aber es kann getan werden.

Zuerst müssen Sie eine strukturierte Übersetzungsfunktion für Ausnahme durch Aufrufen installieren _set_se_translator() (sehen hier) Anschließend können Sie den Code untersuchen, den Sie bei einer SEH -Ausnahme übergeben haben, und eine geeignete C ++ - Ausnahme auswerfen.

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);
}

Dann können Sie einfach Ihre fangen CMyFunkyDivideByZeroException() in C ++ auf normale Weise.

Beachten Sie, dass Sie Ihre Ausnahmeübersetzungsfunktion in jedem Thread installieren müssen, von dem Sie Ausnahmen übersetzt haben.

Andere Tipps

C ++ handelt nicht als Ausnahme, pro-se.

Stroustrup zitieren:

"Ereignisse mit niedriger Ebene, wie arithmetische Überläufe und dividieren durch Null, werden eher von einem speziellen Mechanismus mit unterer Ebene als durch Ausnahmen behandelt. Dies ermöglicht C ++, das Verhalten anderer Sprachen in Bezug auf Arithmetik zu entsprechen. Vermeidet die Probleme, die auf stark pipelierten Architekturen auftreten, bei denen Ereignisse wie Divide durch Null asynchron sind. "

"Das Design und die Entwicklung von C ++" (Addison Wesley, 1994)

In jedem Fall sind Ausnahmen noch nie Ein Ersatz für die ordnungsgemäße Voraussetzung.

Um die Divide durch null Ausnahmen in visueller C ++-Try-> catch (...) Aktivieren Sie /EHA-Option in Projekteinstellungen zu erfassen. Sehen Projekteigenschaften -> C/C ++ -> Codegenerierung -> Ändern Sie die C ++ -Annahmen in "Ja mit SEH -Ausnahmen" aktivieren.. Das ist es!

Siehe Details hier:http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

Sie können entweder eine strukturierte Ausnahmebehandlung (mit __try usw.) verwenden oder einen strukturierten Ausnahme -Handler -Übersetzer installieren: _set_se_translator

Beide sind Betriebssystemspezifische.

Sie können dies nicht mit Standard C ++ tun, da es sich nicht um Standard -C ++ -Ausnahme handelt. Es ist eine strukturierte Ausnahme. Für die Standard -C ++ - Ausnahme muss jemand a machen throw exception; Aus dem Code.

Warum nicht vorher darauf suchen? Die Leistung wird für eine einfache trivial sein j == 0 Im Vergleich zum Kontext-Schalter für Ausnahmebehandlung.

Probieren Sie den folgenden Code aus:

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"); 
}

Wenn Sie dies ohne Ausnahmen in Ordnung tun, könnten Sie natürlich:

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

Bearbeiten Sie als Antwort auf Klarstellung: Sie müssen herausfinden, welchen Eingang Sie den Dritten geben, der sie vor Null vor der Hand trennen, und dies zu tun, bevor sie ihre Funktion jemals aufrufen.

Ein guter Ansatz wäre die Verwendung sicherer objektorientierter Wrapper wie Sicher. Es auch scheint integriert zu sein In Visual Studio 2010.

aktualisieren:
Wenn der Division durch Null im Code von Drittanbietern stattfindet, ist Ihre einzige Option SEH oder etwas Äquivalentes wie Beantwortet von Seb Rose

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top