简体   繁体   中英

Catch a run-time exception

Following fails to catch a exception

int *i;  //intentionally uninitialized

try {
      *i = 6;
    }
catch (const runtime_error e) {
      cout << "caught!" << endl;
    }

is it actually catching a runtime error or an exception?

The line *i = 6; does not throw a runtime_error ; it results in undefined behavior.

The uninitialized pointer will be dereferenced and your program will try to write the value six to wherever it points (if it points anywhere). This results in undefined behavior. In most cases, this means your program will either crash immediately or will crash later on because you will have corrupted something important in memory.

There is no way to "catch" this sort of error as an exception in standard C++; you need to write your code such that you don't do things like this.

Disclaimer

This kind of thing is no good except for debugging. There aren't many legitimate reasons to continue your program after a memory access exception, because usually it indicates data corruption.

That said, I think it's better to answer the question than to pass judgment, censure, or censor it.


The C++ classes derived from exception are simply conveniences to encourage good practice among programmers. They have no special semantics, and aren't differentiated in anything but name.

Worse, C++ exceptions cannot pass outside a signal handler (what in other languages would be called the "exception handler," the function which is called upon the illegal access). The standard has a specific warning about this,

A [plain old function] that could be used as a signal handler in a conforming C program does not produce undefined behavior when used as a signal handler in a C++ program. The behavior of any other function used as a signal handler in a C++ pro- gram is implementation defined.213)

213) In particular, a signal handler using exception handling is very likely to have problems

That said, if you want to catch this, use the UNIX signal facility to install a function that does not use C++ features.

#include <csignal>
#include <cstdlib>
#include <cstdio>

void catch_memory( int ) {
    std::printf( "caught!\n" );
    std::abort();
}

int main() {
    std::signal( SIGSEGV, catch_memory );

    int *i = 0;
    *i = 6;
}

This is not a runtime error, it is undefined runtime behaviour due to a compile time error.

To catch it (and many others like it), set your compiler to the highest warning level possible. (As compilers, contrary to Martin's comment, do check if you are stupid if you let them.) gcc -Wall would have done it in this case:

$ g++ -Wall test.cpp 
test.cpp: In function ‘int main()’:
test.cpp:<line>: warning: ‘i’ is used uninitialized in this function

Personally, I prefer something along these lines:

$ CXXWARN="-Wall -Wextra -Werror -pedantic -Wno-unused-parameter \
         -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \
         -Wmissing-declarations -Wredundant-decls -Winline"
$ g++ $CXXWARN test.cpp

Your mileage may vary.

Appropriate catch clause gets executed when an appropriate exception is thrown using the C++ throw keyword. These are C++ exceptions.

What you get with the OP code is probably a system generated exception (not C++ exception) and strictly it is an undefined behavior.

It does not throw exception. It could lead to crash. If you are working in a project, first thing is, get it reviewed by your peers. Code reviews are very helpful most of the time. If not, you can catch such bugs early in the development cycle by doing using static code analysis tools like Klocwork and Dynamic code analysis tools like Purify, Bounds Checker etc.

Microsoft created something called structured exceptions several years ago (aka, SEH for "structured exception handling"). Although there is some similarity between C++ exceptions and structured exceptions, they are fundamentally different things. Personally, I've steered clear of SEH.

SEH allows you to, among other things, recognize when the stack has overflown or there has been a memory access violation. The thing is, there isn't much you can do in these cases: your program's state has been irretrievably broken before your handler gets a chance to run. And while you can't fix "irretrievably broken" your handler is allowed to claim it did (ie, you can continue executing even though your stack has been smashed).

So your catch block isn't getting executed because the exception you're trying to catch is a Windows-specific extension that uses an entirely different system.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM