C++, _Try and Try/Catch/Finally

What's better to use, a __try/__except block or a try / catch block?

You should use a try/catch block.

As others have already answered, __try / __except is for catching SEH (windows generated errors) not for catching general exceptions.

Most importantly, __try and __catch may not run C++ destructors or correctly unwind the stack when an exception is thrown.

Except in rare cases, you should never try to catch SEH exceptions.

EDIT: Well, I was positive on this (it's what I've always been told), but @Hans says that apparently there is a compiler switch you can use to change this. I think the docs on /EHa are misleading, or at least incomplete, on what happens here. If someone finds definitive docs which prove this wrong, I'll happily remove this answer.

Even if it turns out this is false, you should still use try and catch simply because they are standard, while __try and __except are not.

__try/__finally equivalent in UNIX

This is called structured exception handling. It can be accomplished by using setjmp and longjmp. It has been used in C for a long time. See this for details: http://www.freetype.org/david/reliable-c.html

C : How do you simulate an 'exception'?

Exception-like behavior in C is accomplished via setjmp/longjmp. However, what you really want here is an error code. If all values are potentially returnable, then you may want to take in an out-parameter as a pointer, and use that to return the value, like so:

int pop(double* outval)
{
if(outval == 0) return -1;
if(sp > 0)
*outval = val[--sp];
else {
printf("error: stack empty\n");
return -1;
}
return 0;
}

Not ideal, obviously, but such are the limitations of C.

Also, if you go this road, you may want to define symbolic constants for your error codes (or use some of the standard ones), so that a user can distinguish between "stack empty" and "you gave me a null pointer, dumbass".

c++ try-except statement

__try/__except is a try/catch, for a different kind of exception. You can catch hardware exceptions like floating point violation, bad pointer de-reference, etc, and not C++ exceptions. This is referred to as Structured Exception Handling, or SEH, and MSDN has quite a bit on it if you know where to look.

In this case, they're using it to detect invalid instructions. This is where they attempt to execute instructions that x86 doesn't support, and virtual machines use them. If you're running on a real CPU, then you will get an invalid instruction exception, and if you're running on a virtual machine, you just talked to it.

Preserving exceptions from dynamically invoked methods

Here's the solution I came up with. It gets the job done. I'm still interested in other answers as there might be something easier or cleaner.

  • When you want the functionality of throw; but the exception you want to pass on is not the exception of the current catch block, use throw Functional.Rethrow(e);
  • Replace try...catch... with Functional.TryCatch
  • Replace try...catch...finally... with Functional.TryCatchFinally

Here's the code:

//Need a dummy type that is throwable and can hold an Exception
public sealed class RethrowException : Exception
{
public RethrowException(Exception inner) : base(null, inner) { }
}

public static Functional
{
public static Exception Rethrow(Exception e)
{
return new RethrowException(e);
}

public static void TryCatch(Action _try, Action<Exception> _catch)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
}

public static T TryCatch<T>(Func<T> _try, Func<Exception, T> _catch)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
}

public static void TryCatchFinally(
Action _try, Action<Exception> _catch, Action _finally)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
finally { _finally(); }
}

public static T TryCatchFinally<T>(
Func<T> _try, Func<Exception, T> _catch, Action _finally)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
finally { _finally(); }
}
}

Update

In .NET 4.5 there is the new System.Runtime.ExceptionServices.ExceptionDispatchInfo class. This can be used to capture an exception:

var capturedException = ExceptionDispatchInfo.Capture(e);

And then later this is used to resume throwing the exception:

capturedException.Throw();

Handling specific errors in JavaScript (think exceptions)

To create custom exceptions, you can inherit from the Error object:

function SpecificError () {

}

SpecificError.prototype = new Error();

// ...
try {
throw new SpecificError;
} catch (e) {
if (e instanceof SpecificError) {
// specific error
} else {
throw e; // let others bubble up
}
}

A minimalistic approach, without inheriting from Error, could be throwing a simple object having a name and a message properties:

function throwSpecificError() {
throw {
name: 'SpecificError',
message: 'SpecificError occurred!'
};
}


// ...
try {
throwSpecificError();
} catch (e) {
if (e.name == 'SpecificError') {
// specific error
} else {
throw e; // let others bubble up
}
}

Why does iostream require the exception handler to be called while using vcvarsall.bat to compile 'Hello World'?

Short answer:

Add /EHs or /EHsc to your compilation options as the documentation suggests. It's the most portable option regarding exceptions handling, if you will ever need to execute the same code on Unix machine.



Long answer:

There are two parts to this question. First is why the warning occurs in iostream and the second is what does the warning mean.

Why are there exceptions in iostream?

The default behaviour of streams in C++ is exceptionless - any failure is represented by setting an internal fail bit, accessible with eof(), fail() and bad() functions. However, you can change this behaviour to throwing exceptions on failure by using exceptions() method on stream. You can choose which fail bits trigger exceptions, but the main point is that the code must be there by standard. The warning seems to analyze only that - it notices a possible path where throw occurs and reports a warning.

What does the warning mean?

From the Microsoft documentation (emphasis mine):

By default (that is, if no /EHsc, /EHs, or /EHa option is specified), the compiler supports SEH handlers in the native C++ catch(...) clause. However, it also generates code that only partially supports C++ exceptions . The default exception unwinding code doesn't destroy automatic C++ objects outside of try blocks that go out of scope because of an exception.

The issue is that (for some reason) MSVC compiler by default generates assembly which is wrong according to the standard. Stack unwinding will not be perfomerd when exception is thrown, which may cause memory leaks and other unexpected behaviours.

An example correct C++ code, which has a memory leak under the default setting:

void foo()
{
std::string str = "This is a very long string. It definitely doesn't use Small String Optimization and it must be allocated on the heap."
std::cout << str;
throw std::runtime_error{"Oh no, something went wrong"};
}

int main()
{
try
{
foo();
}
catch (std::exception&)
{
// str in foo() was possibly not released, because it wasn't deleted when exception was thrown!
}
}

So the final answer would be:

  • If you plan to use Structured Exceptions (like divide-by-zero or invalid memory access errors) or use a library that uses them, use /EHa
  • If you don't need to catch SEs, choose /EHs for compatibility with C++ standard and portability
  • Never leave the defaults, always set /EH to one alternative or another, otherwise you will have to deal with strange behaviours when using exceptions.


Related Topics



Leave a reply



Submit