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

12,529

Solution 1

Assuming that you can't simply fix the cause of the exception generating code (perhaps because you don't have the source code to that particular library and perhaps because you can't adjust the input params before they cause a problem).

You have to jump through some hoops to make this work as you'd like but it can be done.

First you need to install a Structured Exception Handling translation function by calling _set_se_translator() (see here) then you can examine the code that you're passed when an SEH exception occurs and throw an appropriate C++ exception.

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

Then you can simply catch your CMyFunkyDivideByZeroException() in C++ in the normal way.

Note that you need to install your exception translation function on every thread that you want exceptions translated.

Solution 2

C++ does not handle divide-by-zero as an exception, per-se.

Quoting Stroustrup:

"low-level events, such as arithmetic overflows and divide by zero, are assumed to be handled by a dedicated lower-level mechanism rather than by exceptions. This enables C++ to match the behaviour of other languages when it comes to arithmetic. It also avoids the problems that occur on heavily pipelined architectures where events such as divide by zero are asynchronous."

"The Design and Evolution of C++" (Addison Wesley, 1994)

In any case, exceptions are never a replacement for proper precondition handling.

Solution 3

To catch divide by zero exceptions in Visual C++ try->catch (...) just enable /EHa option in project settings. See Project Properties -> C/C++ -> Code Generation -> Modify the Enable C++ Exceptions to "Yes With SEH Exceptions". That's it!

See details here: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

Solution 4

You can either use structured exception handling (using __try etc.) or you can install a structured exception handler translator: _set_se_translator

Both of these are operating system specific.

Solution 5

You can not do that using standard C++ as it is not standard C++ exception. It's a structured exception. For the standard C++ exception somebody has to do a throw exception; from the code.

Share:
12,529
thanhbebi
Author by

thanhbebi

See joshuafox.com including links to my blog, published articles, LinkedIn, GitHub, and even StackOverflow :-)

Updated on July 05, 2022

Comments

  • thanhbebi
    thanhbebi almost 2 years

    How can I catch a divide-by-zero error (and not other errors; and to be able to access exception information) in Visual Studio 2008 C++?

    I tried this:

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

    But this goes to the generic ... catch block. I understand that the MS-specific __try may be useful here, but I'd prefer standard C++, and in any case I have destructors which prevent the use of __try.

    CLARIFICATION: The code above is simplified for discussion purposes. Actually, the divide-by-zero is a bug which occurs deep in a third-party DLL for which I do not have the source code. The error depends on the parameter (a handle to a complex structure) which I pass to the library, but not in any obvious way. So, I want to be able to recover gracefully.

  • thanhbebi
    thanhbebi over 14 years
    Thanks, your answer is correct. But I cannot handle the precondition, since the divide-by-zero is a bug which occurs deep in a third-party DLL for which I do not have the source code. (The code I gave above was (over)simplified for discussion purposes.) I need to recover gracefully from the bug.
  • thanhbebi
    thanhbebi over 14 years
    Thanks, your answer is correct. But I cannot handle the precondition, since the divide-by-zero is a bug which occurs deep in a third-party DLL for which I do not have the source code. (The code I gave above was (over)simplified for discussion purposes.) I need to recover gracefully from the bug.
  • Andreas Spindler
    Andreas Spindler about 12 years
    Just want to mention that _set_se_translator works on a per-thread basis and is only useful if you control the creation of all threads. Most likely this falls on your feet when calling DLLs. You simply cannot translate their SEHs. For example, an Excel C AddIn DLL may therefore easily crash the whole Excel process. Only a catch(...) block will catch them - but neither you nor Excel knows which SEH was catched. It could be an EXCEPTION_ACCESS_VIOLATION (alias SIGSEGV on other OSs) in which case you're doomed anyway. I think _set_se_translator creates a false feeling of security.
  • Len Holgate
    Len Holgate about 12 years
    Andreas, that's true, but if you're on a thread that you don't own then you can wrap your function in an SEH exception handler and deal with it as a normal SEH exception and therefore you DO know the type of exception that you caught (you have to jump through hoops and maybe create a extra shim function if you want to catch SEH exceptions in a function that also deals with C++ exceptions). Oh and EXCEPTION_ACCESS_VIOLATION isn't game over, necessarily - the OS is simply telling you that you can't access the memory.
  • Andreas Spindler
    Andreas Spindler about 12 years
    I meant in case of catch(...) naturally you don't know what the type is. Anyway... unless your program is a debugger, spyware or a virus, why would you ever access memory you don't own? In most cases the program is bad. Even in case of a "harmless" NULL pointer access the program can't continue because it will crash again.
  • Len Holgate
    Len Holgate about 12 years
    I'm not saying that you would WANT to access memory that you don't own, just that "you're doomed anyway" is a bit strong, since you can always create a mini dump and possibly still shut down cleanly in many cases.
  • Ben
    Ben about 6 years
    This will work for you, since you are already getting the exceptions, but for anyone trying to use this and not getting anything, you might have to enable floating point exceptions with some ugly code. Here is an example (this is what we use in VS2015, sorry for the bad formatting): // set up floating point divide by zero exceptions _clearfp(); uint32 control_word = 0; _controlfp_s(&control_word, _MCW_EM, _MCW_EM); _controlfp_s(0, ~(uint32) (_EM_UNDERFLOW | _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID), _MCW_EM);
  • J. Merdich
    J. Merdich about 6 years