Question

I'm working on old code that relies heavily on the exception specifications behavior described in the language standard. Namely, calls to std::unexpected() on exception specification violations of the form described below.

foo() throw(T) { /*...*/ }

Nothrow specifications are indeed guaranteed to not throw, but throw(T) ones are expected to be violated both by design and... well, because the standard expects as much and provides a mechanism to handle it.

The reasons for this are tied to the designers decision of using EH also as an error handling mechanism (controlled by its own error class hierarchy) in addition to exception handling. The idiom presented in EH closely mapped to their needs and they took the path of least effort. This is at least how I see it and isn't particularly shocking to me, given the size and complexity of the system.

I'm however now tasked to include new and unrelated functionality and the code isn't behaving as expected under VC++ 9.0, due to the deviation from the standards regarding exception specifications introduced in 8.0. (reference: Microsoft)

I'm trying to find a way to force the standard behavior. Was hoping for a fallback to be offered by the compiler. But there is none.

Am I out of luck and need to change correctly written standard-obedient code running on the 350,000 lines of code with a fully developed error handling class hierarchy? Or can you think of a way that will help me to force std::unexpected() behavior?

EDIT: I'm providing some background information. The system in question is a School Year Calendars Generator for a school serving a little over 4,000 students distributed among, I'm unsure as to some of the numbers yet, 6 grades and ~190 classes, plus 12 virtual (long-distance teaching) classes. MINGW is out of the question as is any compiler other than VC++ 8.0 or 9.0. This is due to regulations pertaining to software serving the Educational System in this country.

The changes needed to the code are exactly to accommodate the introduction of the virtual classes with a vastly different schema for calendar generation. And then I bumped into this problem. The software makes heavy use of the exceptions mechanism on a few parts of the calendar generation process as a means to control workflow through both unexpected() mappings (saved and restored) and bad_exception mappings, none of which work under VC++. On a purely personal note, I find the mechanism in place actually very elegant even if entirely uncommon. But I digress.

Was it helpful?

Solution

As you mentioned, Visual Studio has an "interesting" way of dealing with exception specifications:

  • throw() has its normal meaning (the function must not throw)
  • anything else (including no exception specification) is interpreted as throw(...)

There is no way to circumvent this. However, the C++ community pretty much agrees that exception specifications are useless. Do you really need runtime checking of error types thrown? Perhaps proper unit testing can replace your runtime checks.

OTHER TIPS

I don't believe that Visual C++ exception specification behaviour has ever been (or claimed to have been) standards conforming - even before 8.0 - so I'm not sure how the application has been working.

Is it feasible to perform changes such as:

void f() throw(T)
{
    // ...
}

to:

void f()
{
    try
    {
        // ...
    }
    catch (T)
    {
        throw;
    }
    catch (...)
    {
        app_unexpected();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top