Question

Comment puis-je attraper une erreur de division par zéro (et non d'autres erreurs, et d'être en mesure d'accéder à l'information d'exception)? Dans Visual Studio 2008 C ++

J'ai essayé ceci:

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

Mais cela va au générique ... bloc catch. Je comprends que le __try MS spécifique peut être utile ici en quelque sorte, mais je préfère la norme C ++, et en tout cas je Destructeurs qui empêchent l'utilisation de __try.

CLARIFICATION: Le code ci-dessus est simplifié à des fins de discussion. En fait, la division par zéro est un bug qui se produit en profondeur dans une DLL tiers pour laquelle je n'ai pas le code source. L'erreur dépend du paramètre (une poignée à une structure complexe) que je passe à la bibliothèque, mais pas d'une manière évidente. Donc, je veux être en mesure de récupérer gracieusement.

Était-ce utile?

La solution

En supposant que vous ne pouvez pas simplement corriger la cause du code de génération d'exception (peut-être parce que vous ne disposez pas du code source de cette bibliothèque et peut-être parce que vous ne pouvez pas régler l'entrée params avant qu'ils ne causent un problème) .

Vous devez sauter à travers quelques cerceaux pour faire ce travail que vous le souhaitez, mais il peut être fait.

Vous devez d'abord installer une exception Gestion structurée fonction de traduction en appelant _set_se_translator() (voir ici ), vous pouvez examiner le code que vous passé lorsqu'une exception SEH se produit et lancer une exception appropriée 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);
}

Ensuite, vous pouvez simplement prendre votre CMyFunkyDivideByZeroException() en C ++ de façon normale.

Notez que vous devez installer la fonction de traduction d'exception sur chaque fil que vous voulez exceptions traduisiez.

Autres conseils

C ++ ne gère pas de division par zéro à titre d'exception, per se.

Stroustrup Citation:

  

"événements de bas niveau, tels que l'arithmétique   débordements et division par zéro, sont   supposé être manipulé par un dédié   Mécanisme de niveau inférieur plutôt que par   exceptions. Cela permet à C ++ pour correspondre   le comportement des autres langues lorsque   il est à l'arithmétique. Il évite aussi   les problèmes qui se produisent beaucoup   architectures canalisées lorsque des incidents   comme division par zéro sont   asynchrone. "

"La conception et l'évolution de C ++" (Addison Wesley, 1994)

Dans tous les cas, les exceptions sont jamais un remplacement pour la manipulation correcte de condition préalable.

Pour attraper diviser par zéro des exceptions dans Visual C ++ répar-> catch (...) juste activer option / EHa dans les paramètres du projet. Voir Propriétés du projet -> C / C ++ -> Génération de code -> Modifier l'option Activer les exceptions C "Oui Avec des exceptions SEH" . Ca y est!

Voir les détails ici: http://msdn.microsoft.com/en -us / bibliothèque / 1deeycx5 (v = vs.80) .aspx

Vous pouvez utiliser la gestion structurée des exceptions (à l'aide __try etc.) ou vous pouvez installer un traducteur de gestionnaire d'exceptions structuré: _ set_se_translator

Ces deux éléments sont le système d'exploitation spécifique.

Vous ne pouvez pas le faire en utilisant la norme C ++ comme il est pas standard C ++ exception. Il est une exception structurée. Pour la norme C ++ quelqu'un d'exception doit faire throw exception; du code.

Pourquoi ne pas vérifier cela avant? La performance sera trivial pour un simple j == 0 par rapport au contexte de commutation pour la gestion des exceptions.

Essayez le code suivant:

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

Bien sûr, si vous êtes OK faire sans exception, vous pouvez faire:

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

Modifier en réponse à la clarification: vous devez comprendre ce que l'entrée est que vous remettre le tiers qui les amène à se diviser par zéro avant la main, et que la poignée avant même d'appeler leur fonction

Une bonne approche serait d'utiliser un objet de sécurité des emballages orientés comme SafeInt . Il a également semble être intégré dans Visual studio 2010.

Mise à jour: Si la division par zéro se produit dans le code tiers votre seule option est SEH ou quelque chose d'équivalent comme réponse par Seb Rose

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top