2

I've been reading through the book Teach Yourself C++ In 21 Days , by Jesse Liberty and came across Exceptions and Errors chapter. The author uses this example:

int top = 10;
int bottom = 0;
try
{
    cout << "top divided by bottom = ";
    cout << (top / bottom) << endl;
}
catch(...)
{
    cout << "something has gone wrong!" << endl;
}

And it works fine for him. The exception gets caught and the output is:

top divided by bottom = something has gone wrong!

I tried it myself and received the following error:

Unhandled exception at 0x0124152d in stuff.exe: 0xC0000094: Integer division by zero.

integer division by zero

According to this thread, "Integer divide by zero is not an exception in standard C++." But Visual Studio is obviously throwing an exception here, though not catching it.

I tried defining top and bottom as double, and I received the following output:

top divided by bottom = 1.#INF

So why the try catch block isn't catching the integer division by zero exception?

Community
  • 1
  • 1
Alaa M.
  • 4,961
  • 10
  • 54
  • 95
  • 10
    That's terrible. It's undefined behaviour (and that's not a C++ exception). I knew the book was bad, but this is ridiculous. – chris Oct 11 '14 at 13:15
  • 1
    This doesn't inspire much confidence in that book. – juanchopanza Oct 11 '14 at 13:16
  • 3
    Windows exceptions and C++ exceptions are very different beasts. And I'd suggest burning that book and [getting a better one](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Don't just throw it out - someone else might pick it up. – T.C. Oct 11 '14 at 13:20
  • `try` and `catch` are only for C++ exceptions and not CPU exceptions, those are two orthogonal concepts and totally different despite the similar names. – Some programmer dude Oct 11 '14 at 13:20
  • Seems you are learning - badly - MS visual-C++, and without being told which dialect, not really standard C++. At least as long as you keep to that book. – Deduplicator Oct 11 '14 at 13:29
  • 1
    There should be a book called "Teach Yourself C++ In 21 Years". – Galik Oct 11 '14 at 13:52
  • I think it is rather ridiculous that we have 2022 and there are still OSs, which cannot deal with this in sane way while others got it solved since decades. – Frank Puck May 19 '22 at 17:28

2 Answers2

4

Use /EHa to switch the exception-handling model, so non-C++ exceptions can be caught by try-catch.

Be aware that all asynchronous exceptions will be converted to synchronous if you do so, and you really don't want to catch most.
Thus, not recommended for general code.

As an aside, blindly catching all you can is a known anti-pattern, only catch what you really expect and can handle.

See here for __try-__except, which can always catch asynchronous exceptions: http://msdn.microsoft.com/en-us/library/s58ftw19.aspx

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • Correct me if I'm wrong, but I believe MSVC's `__try` and `__catch` also get these. – chris Oct 11 '14 at 13:18
  • @chris IIRC it's `__except`. – T.C. Oct 11 '14 at 13:21
  • Of course not. Just an alternative to the compiler switch. And woops, shows I don't use them if I can't even remember the right identifier. – chris Oct 11 '14 at 13:22
  • Btw, from the C# I found that exception error handling model is very efficient. And in particular to use it you must catch *everything* you can. It is looks like this: suppose you have a class to work with a network, and higher a class that works with an interfaces like a network, a serials, etc. These classes do not care about an errors, all the handling done much higher. And here could be really many an exceptions: do you want to write these all by hand? In the end these all results to an error message and closing the program. The ones that not you may write separately, though. – Hi-Angel Oct 11 '14 at 13:44
  • @Hi-Angel: I don't understand your comment. If you mean that throwing exceptions and handling them where you know what should be done is the way to go, I concurr. But that's not under question here at all. – Deduplicator Oct 11 '14 at 13:47
  • @Deduplicator you wrote `As an aside, blindly catching all you can is a known anti-pattern`, that was my answer to your words: I disagree that «blindly catching all you can» is a bad idea. – Hi-Angel Oct 11 '14 at 13:49
  • @Hi-Angel: So, what's your response to an impossible error? – Deduplicator Oct 11 '14 at 13:50
  • @Deduplicator I am wrote an example with a network interfaces in the comment. The idea behind this is that you should catch something that you can handle, to handle this. But you should also catch everything else, at least to show an error message, and gracefully close an application. – Hi-Angel Oct 11 '14 at 13:53
  • @Hi-Angel: Bad idea. With that you are overriding the Crash-Report-Collector, aside from possibly making things worse. You already get an error-message for not catching an exception, why replace it with your own which is less detailed and useful? – Deduplicator Oct 11 '14 at 13:56
  • @Deduplicator suppose I have some data that I want to save. If I just ignore an exception, my application going to close, and nothing would be saved. And more: what if I want to send the message about an error through the network? Either I want to save it in some log file? So no, it is definitely bad idea to not catch all an exceptions that you can. – Hi-Angel Oct 11 '14 at 14:00
  • @Hi-Angel If your program is toast (aka its in an "impossible" state), how can you expect that data to be in a consistent and proper state, and how can you expect to be able to properly save it? Hope you at least won't overwrite the previous version, which has a much higher probability for being usable. – Deduplicator Oct 11 '14 at 14:04
  • @Deduplicator i.e. in C# no such a thing like a system errors. If you're communicating via network, and a connection was broken, you got an exception. Also in C++ some functions *(particularly from the c++11 standard)* throws an exception in an usual situations. Anyway, from your words about «impossible state» I suppose you're confusing [the signals](http://en.wikipedia.org/wiki/Unix_signal) *(don't know what have Windows® like this)* which indeed thrown when i.e. was attempt to write read-only memory, or dereference a null pointer. But such a things the «try-catch» statement won't catch. – Hi-Angel Oct 11 '14 at 14:11
  • 1
    @Hi-Angel: An "impossible state" is any state you as the programmer reasoned that the program cannot ever attain, and which you thus justly discarded from further consideration. They normally occur from fatal flaws in logical reasoning, occasional lapse of judgement, sub-modules breaking their contracts, breakdown of the underlying platform and inimical interference from above. Signals, properly handled, are neither of those. Also, none of them are in any way restricted to native code, they can happen in "safe" managed code as well. – Deduplicator Oct 11 '14 at 14:18
  • @Deduplicator hm, I think I got you. Probably I just haven't wrote anything big using an exceptions. Though your words is kinda abstract, but I will take your words in mind just to try to imagine such a situation for a future, and ask me what should have been done to evade this. Because with catching an every exception by it's name such an error handling diminishes it with comparison to an error handling by return codes. – Hi-Angel Oct 11 '14 at 14:30
3

The book possibly overlooked to tell you that you have to compile with /EHa in effect. The default is /EHsc, it doesn't cause these SEH exceptions to be caught by catch (...).

Having catch (...) catch everything isn't very pretty. You would not want this to happen:

int* p = 0;
try {
    int result = *p / 0;
    std::cout << result << std::endl;
}
catch (...) {
    std::cout << "Division by zero" << std::endl;
}

Not actually a division by zero fault, not good of course. The better mouse trap is to translate SEH exceptions to C++ exceptions. You do so by installing a callback that runs when an SEH exception occurs, like this:

#include <exception>
#include <eh.h>
#include <iostream>

class divisionbyzero_exception : public std::runtime_error {
public:
    divisionbyzero_exception() : std::runtime_error("Division by zero") {}
};

void translate_seh_exception(unsigned int exceptioncode, struct _EXCEPTION_POINTERS* pExp) {
    if (exceptioncode == 0xc0000094) throw divisionbyzero_exception();
}

int main(int argc, char* argv[])
{
    _set_se_translator(translate_seh_exception);
    try {
        int result = argc / 0;
        std::cout << result << std::endl;
    }
    catch (divisionbyzero_exception& ex) {
        std::cout << ex.what() << std::endl;
    }
    return 0;
}

Do keep in mind that this is completely unportable.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Are you sure that should not be derived from [`std::domain_error`](http://en.cppreference.com/w/cpp/error/domain_error)? – Deduplicator Oct 11 '14 at 21:14
  • I don't understand that I cannot mention that I upvoted this answer... Thanks for mentioning _set_se_translator()! – Frank Puck May 19 '22 at 17:34