Thanks
Jaap Havinga
void foo()
{
// a throw in a if statement will sometimes cause
problems...
if (condition)
throw CError(arg1, arg2);
...
//a throw on last line, will cause problems: (the throw
is 'reachable')
throw CError (arg1, arg2);
}
void Work()
{
try
{
...
foo();
...
}
catch (CError &e)
{
//correct catch here when /Og switch not set
}
catch (...)
{
// incorrect catch here when /Og switch set
}
}
Do you have a short console application example that would allow
someone to reproduce the problem?
Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq
Jaap Havinga
>.
>
I also get those unreachable warnings from the STL in the release
build of a project I'm currently working on - I don't know why.
I don't believe they are an indication of any particular problem,
though I can't swear that they're not!
Just to be sure, are you setting at least the /EHs switch in addition to
/Og? (You can also use /EHa instead of /EHs.)
If you don't set either of these switches, the optimizer basically ignores
exception handling.
--
Brandon Bray Visual C++ Compiler
This posting is provided AS IS with no warranties, and confers no rights.
Of course, these switches don't mean anything if /Og isn't set. Actually,
setting these switches is really not useful at all. That's what /O1 and /O2
are good for.
/01 == /Ogb2ys /GF /Gy
/O2 == /Ogb2yit /GF /Gy
>.
>
This workaround concerns me though. Isn't there a huge penalty hit for
asynchronous exception handling, and doesn't that also mean you end up
catching win32 structured exceptions? Might be better to just not use /Og if
this is indeed an optimizer bug.
Jeff
As you can see, the penalty on /EHa is not so big. Leaving
out /Og is a bigger penalty. Also it appears that /Ot
and /Os switches do have effect, even if /Og is not set
(This is consistent with the documentation)
Jaap Havinga
>This workaround concerns me though. Isn't there a huge
penalty hit for
>asynchronous exception handling, and doesn't that also
mean you end up
>catching win32 structured exceptions? Might be better to
just not use /Og if
>this is indeed an optimizer bug.
>
>Jeff
>
>
>.
>
I don't think there would be. The main effect of /EHa, as I understand
it, is to tell the compiler that it has to assume that an exception can
originate anywhere and not just from a throw statement. And, as I
understand it, that just means that it's precluded from optimizing away
exception handling machinery in places where it otherwise would do so.
> and doesn't that also mean you end up
> catching win32 structured exceptions?
IIRC (don't have it available to test), VC7 did not change the behavior
of VC6 with respect to catching structured exceptions. They'll always
get caught by catch(...) handlers, but without /EHa the behavior may
not be correct. And, they will only get caught be a catch(...)
handler unless _set_se_translator is used.
--
Craig Powers
MVP - Visual C++
I'd be interested to see how the /EHc switch affects things. Do you still
get the bug if you use /EHs instead of /EHsc? What about /EHac?
Thanks,
Jeff
> >
> > This workaround concerns me though. Isn't there a huge penalty hit for
> > asynchronous exception handling
>
> I don't think there would be. The main effect of /EHa, as I understand
> it, is to tell the compiler that it has to assume that an exception can
> originate anywhere and not just from a throw statement. And, as I
> understand it, that just means that it's precluded from optimizing away
> exception handling machinery in places where it otherwise would do so.
My understanding is that it's much more efficient to implement synchronous
EH. Jaap's test's only show a 3% difference, but I would think it might be
dependent on the number of try blocks in your code or how your code is
structured as to how much difference it makes.
> > and doesn't that also mean you end up
> > catching win32 structured exceptions?
>
> IIRC (don't have it available to test), VC7 did not change the behavior
> of VC6 with respect to catching structured exceptions. They'll always
> get caught by catch(...) handlers, but without /EHa the behavior may
> not be correct. And, they will only get caught be a catch(...)
> handler unless _set_se_translator is used.
Well, the documented behavior in the help says that only async EH catches
structured exceptions:
-Use /EHs to specify the synchronous exception handling model (C++ exception
handling without structured exception handling exceptions). If you use /EHs,
do not rely on the compiler to catch asynchronous exceptions.
-Use /EHa to specify the asynchronous exception handling model (C++
exception handling with structured exception handling exceptions).
Now I haven't done any testing to confirm this, but it was my understanding
that catch(...) was safe with synchronous EH.
Jeff
It's not. When compiled with /EHs, catch(...) will still catch structured
exceptions, unless the compiler optimizes the catch away, in which case it
won't. Worse, under /EHs, C++ objects on the stack may or may not have
their destructors called before the catch is entered (within a particular
code construct, they'll either be called or not - but it's not immediately
clear how to predict which objects' destructors won't be called).
Under /EHs, if there's a section of code that you expect (might) raise a
structured exception, you need to use __try/__except in that block to
reliably catch the SE. That block must not contain C++ objects with
destructors (on the stack) because their destructors may not be run.
Bottom line: if you expect to structured exceptions to be raised and your
code contains any catch(...) blocks, you must compile with /EHa, or do all
the SE handling yourself to get reliable operation.
-cd
I'm not aware of any differences between /EHa and /EHs exception
handling that would make the latter more efficient, except in the sense
that the former precludes optimizations because it tells the compiler
that any statement (not just an explicit throw) might generate an
exception. AFAIK, the actual exception handling implementation is
exactly the same for both switches.
As you say, EHa precludes optimizations because (1) try/catch blocks cannot
be optimized away, and (2) instruction reordering needs to preserve the
asynchronous exception semantics of the program. With EHs, performance can
improve because (1) try/catch blocks can be optimized away if the body of
the try block provably has no throw statements, and (2) instruction
reordering needs only preserve the synchronous exception handling semantics
which gives the optimizer much more freedom.
This also explains why the 'c' in EHac isn't interesting and why it is for
EHsc. Under EHa, no try/catch or __try/__except block is ever optimized
away, so there is no analysis needed of the try or __try blocks to see if
any exception could occur. With EHs, since there is analysis done, the
optimizer is limited to the information it has on hand (which is only what
is available in the translation unit). EHsc gives the optimizer more
freedom -- it allows it to assume that an extern "C" function does not have
a throw statement (or does not call any other function that has a throw
statement). This widens the possibility that the try/catch block is not
needed. (It is also worth noting that Link Time Code Generation via /GL can
improve this optimization, as the optimizer can search the call graph for
the entire program looking for throw statements.)
If a translation unit has any __try/__except blocks, it should be compiled
with EHa. If there are no __try/__except blocks in a translation unit, EHs
is appropriate (unless you're using _set_se_translator). Provided a
translation unit was compiled with either EHs or EHa, the correct stack
unwinding semantics will take place for at least the C++ EH model.
The fact that catch(...) will capture an ansyncronous exception (as long as
the associated try block was not optimized away) is a bug. We intend to fix
this for EHs in a future release. After this is fixed, there are two
programming errors that a developer can make:
- C++ EH (aka synchronous EH) can handle SEH in /EHa. There is a
_set_se_translator function that makes this sound. Forgetting to
call this function and having catch(...) in the code is a problem.
- SEH can handle C++ EH. The danger is when the C++ exception is
thrown by value - when SEH handles the exception, the C++ exception
object will not have its destructor called but its memory will be
freed. The recommended practice is of course to always throw a
pointer to a C++ exception object (of course, this can be tricky).
Hope that helps!
Without seeing code, I cannot say anything for sure. If there is no throw
statement as you say, I would expect the optimizer to remove the try/catch
block under EHs.
According to the code you put in the original post, I would not expect
problems with /EHs as you did have throw statements. If that is
representative of your code, I'm a little concerned. Can you reproduce your
problem in an example that we can use to investigate?
Thanks!
> The fact that catch(...) will capture an ansyncronous exception (as long
as
> the associated try block was not optimized away) is a bug. We intend to
fix
> this for EHs in a future release.
So would I be correct in assuming that "future release" is not VC 7.1? If
not that's a shame, this seems like a pretty serious bug.
Let me explain my situation. I don't want to catch/handle Win32 SE's; if my
program performs an Access Violation or some such, I'm perfectly happy with
the default handling (ie terminate the program). That said, I do use
catch(...) on occasion. For instance, the COM interface methods in an ATL
COM server will be wrapped in try/catch blocks that use catch(...) as a last
resort because I want to be absolutely sure that no C++ exceptions escape my
component. So what can I do to safely use catch(...) in these situations
without having to worried about Win32 SE's silently getting caught? What I
would really like to do is use /EHsc and just not worry about Win32 SE's,
but it sounds like that's not an option due to the bug you mention. So is my
only real option to use /EHa and install an _se_translator_function to
handle Win32 SE's. Then again I'm not even sure if that's safe to do in a
COM component whose threading model is "neutral" or "both"
BTW, I have also noticed that /EHsc in combination with /OG produces C4702
warnings for system headers, such as <xtree> and <vector>. I don't know if
this is just something that can safely be ignored or an indicator of the
possible bug Jaap is reporting, but it does concern me somewhat because I
always try to compile cleanly at level 4 and I'd have to have to disable
this warning since it does have its uses.
Jeff
Jaap Havinga
>.
>