Blair,
This is slightly off-topic, but not really given that just about any Smalltalk needs the occaisional boost from a more staticically-typed language, and because I have C++ questions that (I suspect) only other Smalltalkers will understand. I recently did some C++ programming that reminded me of my lack of knowledge about/confidence in C++ exception handling. You won't like it<g>, but I've been using MinGW lately, falling back on VC++ for things that cause trouble otherwise. However, most if not all of my coding experience with C++ excpetions has been with MFC macros. The C++ books on my shelf at home describe try/catch, but Google searches quickly turn up different implementations and question the thread safety of at least some of them. Is C++ exception handling in chaos, or are the posters confused? Do you recommend any particular implementation or know of good reading on the subject? Apparently one has the choice to pass exception arguments as pointers vs. references, and there _must_ be issues with memory management. Any recommendations on the best way to proceed? [See what I mean about having to ask these questions of Smalltalkers? :)] What does one do for an analog to #ensure:? #ifCurtailed:? Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
"Bill Schwab" <[hidden email]> wrote in message
news:b3ofs4$1n9ehh$[hidden email]... > Blair, > > This is slightly off-topic, but not really given that just about any > Smalltalk needs the occaisional boost from a more staticically-typed > language, and because I have C++ questions that (I suspect) only other > Smalltalkers will understand. I recently did some C++ programming that > reminded me of my lack of knowledge about/confidence in C++ exception > handling. > > You won't like it<g>, but I've been using MinGW lately, falling back on > for things that cause trouble otherwise. However, most if not all of my > coding experience with C++ excpetions has been with MFC macros. The C++ > books on my shelf at home describe try/catch, but Google searches quickly > turn up different implementations and question the thread safety of at least > some of them. Is C++ exception handling in chaos, or are the posters > confused? Do you recommend any particular implementation or know of good > reading on the subject? > > Apparently one has the choice to pass exception arguments as pointers vs. > references, and there _must_ be issues with memory management. Any > recommendations on the best way to proceed? [See what I mean about having > to ask these questions of Smalltalkers? :)] > > What does one do for an analog to #ensure:? #ifCurtailed:? Hi Bill, I regularly use C++ exceptions [and Window SEH and .NET mechanisms] in addition to those within Smalltalk/S#. Standard c++ does not provide for the notion of "resumable" exceptions, VC++ using the underlying Microsoft SEH (structured exception handle) platform model does provide this support. The S# language implementation (Smalltalk design) is layered on the SEH model (with some optimizations), which means you can catch any exception (Smalltalk or otherwise) and manage it. [sorry for the little S# commentary, but it was worth noting]. In standard c++, once the exception "hander" has been invoked for a particular "guard" expression, all intervening method frames (from the point of the exception on up the stack to the guarded-method frame) have effectively been unwound already [see temporal-issues questions regarding c++ standard at the end]. In c++ (as you know) the full expression form is: try { } catch("guard filter expression => var-type + optionally a var") { "handler code" } In VC++ we can use the extended forms: __try { } __except(ExceptionFilter(GetExceptionInformation())) { } __finally { } The extended form in vc++ allows us to provide a function for the "guard-filter". That filter serves two purposes. First it allows us to algorithmically take action regarding the "Signal/Warning/Exception" before the frames between the faulting method and the guard have been unwound, and it allows us to tell the exception mechanism what to do once our filter is finished. I.e., resume-execution, continue-looking-for-a-suitable-handler, stop-and-call-my-handler. Which means that (resumable) Smalltalk style exception handling is actually implemented in the vc++/SEH style "guard-filter" itself, whereas c++ handling is implemented in the "handler" block of SEH behavior. The second thing we notice about the extended form is that we have a "finally" clause which is used to declare code we want to have executed whenever the "try" block finishes "OR" is prematurely terminated due to an exception fault unwinding it. So, to distinguish between a "curtailed" and a "non-curtailed" Smalltalk style exception unwind we would have to add a little to the sequence. bool wasCurtailed = true; __try { ... our try body here ... wasCurtailed = false; } __except(ExceptionFilter(GetExceptionInformation())) { } __finally { if(wasCurtailed) ... else ... } I should also add that all versions of XP and later provide for dynamic SEH exception filters (first chance filters) which can be registered on a thread and will come ahead of normally stack-discipline exception guards. This latter capability is very useful for many operations where you need to handle/hide extrinsically triggered exceptions which c++ model code cannot deal with. I should also point out that c++ only traps c++ exceptions, whereas the VC++ extended form allows capturing of signals, warnings, exceptions etc which includes interrupts (including INT3/DebugBreak), faults, and the like. Microsoft's .NET CLR (common language runtime) mechanisms are fairly similar to the SEH model except (for non-specific reasons) the guard-filter does not support "resume-execution" semantics. >From .NET IL we have: .try <il_start_range> to <il_end_range> filter <il_filter_label> handler <il_start_range> to <il_end_range> // catch "<type> handler ..." are optional here finally handler <il_start_range> to <il_end_range> fault handler <il_start_range> to <il_end_range>. Generally coded as: .try { ... } filter { ... endfilter } "handler" { ... } finally { ... } fault { ... } This effectively corresponds to S# equivalents of the form: try [ ] "we can have multiple catch clauses and discrete handlers here" catch("filter-expression including closures etc") [ "handler is executed during the filter" "if recoded in .NET/VC++ handler body is no-op" ] finally [ ] fault "or ifCurtailed" [ ]. Where the keyword variable <thisSignal> can be referenced where needed, or a variable to hold <thisSignal> can be declared as a parameter to a handler block. The (typically less-efficient/more-cumbersome-nesting) classic resumable ANSI Smalltalk exceptions subset of the above would look like: [ [ [ ...place actual try body here... ] on: exceptionFilter do: [:signal| ...exception handler body... ]. ] ifCurtailed: [:signal| ...curtailed/fault handler body... ] ] ensure: [:signal| ...finally handler body... ]. As to the question of "pointer" versus "new-inst" form with exceptions, you do need to be careful. It really helps to understand the temporal semantics in question for c++ [which, as I now realize in writing this -- see below -- I am not so sure about]. Which is that the given exception-handler is logically invoked "after" all the intervening frames have been unwound. In practice they will probably not have been unwound yet (come to think about it, I'm sure the c++ spec must say something about this timing). What that means is that it is probably safe to use an "auto/stack" allocated exception in a throw since the stack has not actually been unwound when the guard is invoked. But if stack unwind semantics (maybe specified in C++ standard) result in the destructor being called on the (auto/stack) allocated exception before you get it, then you are getting an exception structure whose memory still exists but which has already had its destructor invoked. I.e., generally the destructors in an exception do nothing so this is a non-issue. I could go look at the c++ spec/tome for clarification, but I will leave this to someone with a bit more time for such digging. Cheers, -- Dave S. [www.smallscript.org] |
In reply to this post by Bill Schwab-2
Ahh, a question I feel remotely qualified to answer :-).
Bill Schwab wrote: > > You won't like it<g>, but I've been using MinGW lately, falling back on VC++ > for things that cause trouble otherwise. However, most if not all of my > coding experience with C++ excpetions has been with MFC macros. The C++ > books on my shelf at home describe try/catch, but Google searches quickly > turn up different implementations and question the thread safety of at least > some of them. Is C++ exception handling in chaos, or are the posters > confused? Do you recommend any particular implementation or know of good > reading on the subject? > Probably the best reading on exceptions in C++ are Herb Sutter's two books (Exceptional C++ and More Exceptional C++), which are expanded versions of his various C++ Guru of the Week articles posted on the net over the years. I haven't actually read the books, but I hear they are quite good. He talks especially about writing classes that are exception safe. There's beginning to be a good corpus of knowledge about how to do that. > Apparently one has the choice to pass exception arguments as pointers vs. > references, and there _must_ be issues with memory management. Any > recommendations on the best way to proceed? [See what I mean about having > to ask these questions of Smalltalkers? :)] > According to Scott Meyers' _More_Effective_C++_ Item 13: "Catch exceptions by reference". He goes into a lot of detail about why. In a nutshell, catching by value can cause "slicing" of the exception type (catching a base exception object by value when a derived exception object was thrown) and catching by pointer brings up object lifetime issues as you suspect. If you're writing a lot of C++ code, I'd recommend Scott's books (Effective C++, More Effective C++, and Effective STL). He's got a CD out that has the first two plus some bonus material. In my opinion, he's done a really nice job with the CD version - searchable, good cross-references, etc. > What does one do for an analog to #ensure:? #ifCurtailed:? > C++ has an idiom that is worth knowing here. It's relatively unique to C++ because it can't effectively be done in a garbage collected language (due to the non-determinism involved in when or if objects will get finalized). The idiom is called, for reasons I don't really understand, "Resource Acquisition is Initialization" or RAII for short. Basically, the idea is that the stuff that you would normally put in an #ensure: or finally clause in Smalltalk or Java respectively goes into a destructor in C++. Often, you will introduce small classes for this, and you may resist that at first. However, I find that it really helps my code a lot when I do this. C++ smart pointers are examples of this idiom, and you can do similar things when acquiring any external resource (locks in multi-threading code, handles in Windows, file handling, etc.). By reading Herb Sutter's stuff, you'll find that this idiom is one of the techniques at the heart of writing exception-safe code without needing to catch a lot of exceptions. I find in my code that I pretty much never have to worry about memory or other resource leaks in my code, and the code reads much better as a bonus. Another advantage is that it means that clients of your code (including your future forgetful self) don't have to remember to call the cleanup code after every use of your class. I've never used #ifCurtailed:, but after reading the method comment, I'm not sure how you could handle the non-local return part of it in C++ (although David Simmons' response mentions an idea). For anything else, you would put the code in the catch() clause. My gut reaction is that I'd try to write code that didn't need #ifCurtailed:. Somehow it seems like a bit of a code smell to need that kind of knowledge. Yet, browsing through some of the senders of it in Dolphin, I can see some valid uses for it. Hope this helps. Ask for clarification if you need it. Randy -- Randy Coulman NOTE: Reply-to: address is spam-guarded. Reassemble the following to reply directly: rvcoulman at acm dot org |
Free forum by Nabble | Edit this page |