Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 20 Nov 2005
Offline Last Active Oct 31 2015 05:42 AM

Posts I've Made

In Topic: I'm sleepy and confused: __try, __except, /EHa, C2712 (unwinding)

04 October 2015 - 12:44 AM

No shit sherlock *massive-facepalm*. Why did you even write that? Was it not crystal clear that discussions (at least without a lot more details) in that direction is undesired waste of everyone's time?


As i wrote: "ATTEMPT surviving broken code /.../ something that is normally undesirable".


PS. Since you like to ASS-U-ME stuff about what is or is not sensible for me to do in my specific case: the code runs in kernel land and some in user land via callbacks - there is no way for the OS to survive or cleanup anything when the program is broken (the process cannot even be terminated because it is in essence part of the kernel at that point - so, you get kernel panic ... BSOD). However i can send a message and initiate a proper teardown and hope the corruption has not already wrecked the OS (the chances happen to be actually pretty good that the OS will remain unharmed [ie. all internal structures in valid state]). An approach that is highly desirable, in my case, while in development phase.


So, no, you could not be more wrong. Don't assume you know the necessary context and details of what i am doing to ignore my PS'note in OP. It is exceedingly unhelpful.

In Topic: I'm sleepy and confused: __try, __except, /EHa, C2712 (unwinding)

03 October 2015 - 01:40 PM

C++ exceptions are built on SEH. It will quite happily execute any C++ handlers along the way when unwinding.

Really, this is your misunderstanding.

I was stating a fact (it has been this way at least a decade). C++ exceptions are implemented using SEH functionality in VC++.

/EHa causes the compiler to emit code such that SEH exceptions are handled like C++ exception, meaning they'll be caught by catch(...). Plain and simple.

Superficially true. To be specific:
* SEH exception filter for catch(...) does not select only C++ exceptions anymore (which it normally would).
* Optimizer can not rely on throws anymore and needs to emit all the unwind code it normally would omit.

An SEH will not otherwise cause destructors to get invoked during unwinding, because the SEH mechanism knows nothing aout the C++ runtime model.

That is messed up. SEH does not need to know anything about the unwind payload - C++ exceptions or otherwise.

SEH are not C++ exceptions, unless you use /EHa.

This is completely backwards.

Only C++ exceptions invoke C++ destructors.


You need to use try/catch (and not __try/__except) to use C++ exceptions.

Incorrect in principle. C++ exception catching is done via SEH exception records where C++ exceptions have the exception code 0xe06d7363. You are free to handle C++ exceptions in your __except - which, granted, is quite silly.

I suspect the compiler is just trying to save you from the consequences of your misunderstanding.

Incorrect. Compiler just can not do object unwinding in a function scope that also has __try ... which overloaded my sleepy brain - i just was not aware of that limitation (have Googled around since then and it is a well known limitation, but like i said - could not pinpoint any specific reason for it).

PS. You are well advised to assume i am not totally talking out of my ass. Example code:
struct Test {
    Test() { out << L"new Test"; }
    ~Test() { out << L"del Test"; }
    void panic() {
        throw 42;

void snafu() {
    out << L"shit's gonna hit the fan ...";
    Test obj;

    out << L"exception code: " << std::hex << e->ExceptionRecord->ExceptionCode;
    // second parameter in c++ exceptions is a pointer to thrown object (plain int in this case)
    out << L"C++ exception payload object: " << std::dec << *(int*)e->ExceptionRecord->ExceptionInformation[1];
    // yeah, we will take anything - including the C++ exception.

void test() {
    __try {
    } __except(filter(GetExceptionInformation())) {
        out << L"panic averted";
Output (compiled with the default /EHsc option) as one would expect:
shit's gonna hit the fan ...
new Test
exception code: e06d7363
C++ exception payload object: 42
del Test
panic averted

In Topic: I'm sleepy and confused: __try, __except, /EHa, C2712 (unwinding)

03 October 2015 - 12:35 AM

Erm, you are confused or not expressing yourself clearly enough for me.


C++ exceptions are built on SEH. It will quite happily execute any C++ handlers along the way when unwinding. So, of course all the destructors etc will be called - as long as compiler did add them to the unwind stack to begin with. VC++ compiler is free to optimize out adding thous when it sees that there can not be any exceptions (default compile options). To do that it only considers explicit exceptions (throw) by default. That is where "/EHa"  comes in - it disallows such optimizations and hence the entries will be there for even non-explicit exceptions (integer division by zero, access violation, etc).


My findings, based on and sanity-confirmed in practice:




My problem was caused by using "__try" in function scope that needs to unwind objects - which it cannot compile for some unknown reason i was not able to precisely pin down (might be some limitation of the function level handler that "__try" installs - ie. it can not add/remove unwind entries on the fly as functions with "try" can or more likely, the compiler is just not programmed to do so).


Which makes the solution obvious - move "__try" to a function scope that does not have objects to unwind. Unfortunately, in my case that would wreck readability - so, have to use "try catch(...)".


Examples for the benefit of passers by:

struct Test() {
    Test() { out << L"new Test"; }
    ~Test() { out << L"del Test"; }
    void crash() { out << *(int*)(0); }
void func() {
    Test foo; // Perfectly fine to unwind this object (Needs /EHa of couse as otherwise the code needed for unwind would be optimized out as "foo.crash" has no explicit "throw")
void test() {
    // Test notOkay; // Cannot compile this. Function uses __try and needs object unwinding.
    __try {
        out << L"crashed";

In Topic: "defer": is this silly / broken?

09 December 2014 - 03:20 PM

The first problem that comes to mind is that you're executing arbitrary code inside a destructor. If that code throws an exception during stack unwind then your program could turn into a big puddle of goo.

True that.

Did not even think about that as exceptions are not relevant for me. Exceptions are usually disabled in my projects (well, depends) - currently writing a system driver for some personal stuff. Exceptions are completely and utterly useless there:
* memory allocation cannot throw exceptions.
* all inputs must be validated all error conditions must be checked etc.
* there are no meaningful c++ exceptions.
* ... leaving only inherently unrecoverable exceptions via SEH (just catch the exception via first chance handler and try to teardown the driver - is the only sane thing i can do).

... but the point is valid. Speaking of which:

Without commenting on the potential technical pitfalls of your implementation...

that would actually be what i am most interested in. I am wary of using questionable new stuff i have come up with ... debugging bluescreens is not fun (especially as i do not have kernel debugging capabilities right now - it is just not worth it).

The only "advantage" your approach has is that lets you execute an arbitrary block of code defined at the scope's point in the source code. I'm not actually sure that's a good thing, though:

Neither am i, to be honest - "There be dragons".

"It suggests to me that the abstraction you are working with is poor; that the objects in question don't have properly written destructors or related cleanup semantics"
If it would be correct/convenient to use destructors of related objects - i would do that. My interest for "defer" came from run-once initialization functions where there were no meaningful objects for encapsulation. Nor convenient or meaningful ways to compartmentalize in functions ... which reminding me Go for an alternative.

PS. Do not confuse "interest" with "burning need" here - in case i am not being clear. The wast majority of time destructors/constructions/std-helpers are correct and/or convenient.

"It implies you have to violate the general recommendation to declare variables as close to their first use as possible in C++, if you want those variables to subject to the cleanup code that the "defer" mechanism provides, making for potentially sloppier code."
Sorry, could you rephrase that? I think i hit a language barrier (my English is actually fairly poor) - however many times i read it, i just can not follow. sad.png

"I think it hurts readability to put code outside it's execution order like that"
One of my golden rules: a system should try to prevent accidental mistakes and not intentional ones (without a bloody good and clear reason). One can easily write some unbelievably unreadable spaghetti using whatever language construct - or improve readability when using the same construct sensibly. So: yes and no. Blame the user and not the system.

"and I certainly find the macro hackery to introduce a new "syntax element" offensive."
Interesting. Is it because of macro usage in principle or because there is some legitimate problem with the macro (ie. opportunity for likely accidental mistakes)?

I can't really see a great use-case for this that isn't about cleanup code.

I agree. It is quite similar to try/finally, but not interchangeable from readability/use standpoint ("finally" block is not necessarily related to what is immediately before "try", whereas that is the only sane option for "defer" - ie. "defer" keeps the closely related code together).

You have seen it before. Anything that wraps a resource and destroys it when the wrapping object goes out of scope is effectively doing the same thing.

Which bit are you amazed by? Destructors? Function pointers?

You are being facetious. Or at least seem to.

One once said that "Whiles, procedures and case structures are mental masturbation. They're all compiled to a bunch of goto's anyway."

What i am talking about, as i said, is "defer" as in http://golangtutorials.blogspot.com/2011/06/control-structures-go-defer-statement.html in C++, wondering about its usefulness and most importantly - does it break somewhere? ie. Arbitrary finalization code without needing a special separately described object for the occasion and keeping the one-of closely related code together.

C++ does not have any comparable language construct (closest match would be try/finally [non-standard] and, less so, RAII). My facsimile seems to fit the bill.

In Topic: Why is math transformation taxing to most CPUs?

09 December 2014 - 10:30 AM

[...] and threads (2-8 as many operations per clock, if being unrealistically ideal) [...]

I nearly blew a fuse reading that. Please tell me that's a typo, and not how you think threading improves performance.

"if being unrealistically ideal".

His example was detailing the higher/upper bound and is correct as such. Reality of it is irrelevant in that context.

edit: or did you get the impression he is not talking about hardware threads (cpu cores and HT if available ... typically 2-8)?