Thread View: comp.std.c++
2 messages
2 total messages
Started by Herb Sutter
Wed, 22 Nov 1995 04:46
Exceptions and dtors
Author: Herb Sutter
Date: Wed, 22 Nov 1995 04:46
Date: Wed, 22 Nov 1995 04:46
101 lines
6054 bytes
6054 bytes
PROBLEM: Basic Inconsistency (Ctors and Dtors and Exceptions) It's occurred to me that the basic inconsistency in current exception rules still hasn't been resolved: - On one hand, exceptions are (among other things) meant to be a way to provide error handling mechanisms for ctors, since ctors cannot return error values. This is not only legitimate, but elegant and necessary. - On the other hand, under current rules we dare not use exceptions to provide error handling mechnisms for dtors, even though these share the same problem with ctors (both cannot return error values). Briefly, this is because the dtor might be called during stack unwinding while another exception is already active, and under the current rules any further exceptions thrown in that state abort the program. I'm not convinced that last 'must abort' rule is necessary. It seems clear to me that the ctor and dtor needs are quite similar and that excluding one from using exceptions as error returns (not by language rule, but by making it so dangerous as to be shunned) is most unfortunate... particularly since the dangerous case is rare and the vast majority of the time dtor exceptions would be fine even now. PROPOSAL: Allow Multiple Simultaneous Exceptions Consider a change in the rule for exceptions thrown during stack unwinding (note: this proposal doesn't affect any other part of the standard, it doesn't impose burden on code not making use of it, etc.). Suppose that an exception is active and the stack is being unwound, and while one dtor is being processed it throws its own exception... instead of arbitrarily halting the program, we simply add the new exception to the existing list of active exceptions; the dtor throwing the new exception is naturally exited (just as a ctor that throws is exited), but destruction continues as usual... the program first calls dtors for member objects, then the base dtors, etc. Informally, the program continues stack unwinding as before, except that now two exceptions are known to be active and the dtor that threw the second exception naturally didn't complete because it threw. Basically all that's now needed is a rule for when to stop. There seem to be two main possibilities. In both, we keep unwinding (and possibly adding new exceptions as we go) until a handler for any one of the active exceptions is found (if there are two exceptions of the same type, use some rule, e.g. "first thrown first handled", to define which gets handled first). Then, either: a) discard all other active exceptions and continue execution from the handler for the first matched exception (this may allow other errors to be left unhandled, but there may be valid arguments in favour of this, e.g. 'but that's the first handler that claimed it could do something about this tragedy with possibly multiple symptoms [exceptions], and since the exceptions are likely related this handler is probably the one we should want since it does in fact know how to handle a symptom'); or b) invoke the matching handler, remove the handled exception from the list, then continue unwinding (adding any new exceptions if they're thrown and invoking handlers to get rid of active exceptions as valid handlers are encountered) until we've handled the last active exception, then continue progam control flow from after that handler (I like this better in some ways and there may be arguments for this as well, e.g. 'this way all our individual errors/symptoms get specifically addressed', but (a) also has its share of elegance and arguments). ADVANTAGES: This scheme allows exceptions to be properly and safely used in dtors. By far the majority of the time dtors aren't being called in the context of an exception anyway, and so the current rules impose undue hardship by making dtor exceptions so unsafe as to be unusable (because even one at a bad time could crash the program), when in fact even now dtor exceptions are already safe the vast majority of the time. The rules just make the 'rare' case so incredibly dangerous that it can't be risked and must be avoided completely. In so doing, the current rules create an inelegant -- and, worse, inconsistent -- partial solution that addresses half the problem (errors in ctors, for ctors can't return values) while leaving the identical other half unaddressed (errors in dtors, for they have the same restrictions as ctors and the problem is basically no different). SUMMARY: It seems clear to me that the main question with the above is probably: 'When do we stop unwinding?' That is, do we stop as soon as we can handle any of the active exceptions? when we've handled all of them? or something else? Personally, I think that either of the first two answers would probably be fine and so complicated rules should be unnecessary, but only further discussion can prove or disprove that 'I think that...'. :-) Comments and discussion welcome. Herb ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184 Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019 --- [ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu. Contact address: std-c++-request@ncar.ucar.edu. The moderation policy is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Exceptions and dtors
Author: Dick Menninger
Date: Tue, 28 Nov 1995 00:55
Date: Tue, 28 Nov 1995 00:55
130 lines
6469 bytes
6469 bytes
> ==========Herb Sutter, 11/21/95========== > PROBLEM: Basic Inconsistency (Ctors and Dtors and Exceptions) [discussion focused on ctors and dtors deleted] Actually, the inconsistency seems more basic, though what was said seems true. Any code, including code called in ctors, dtors, and exception handlers or implied execution in the companion unwinding that must occur should be capable of being common use code that can want to throw exceptions independent of any other exception already thrown. From an application design viewpoint, THIS IS NOT A RACE with the first exception thrown winning and the rest swallowing their "pride" and going quietly away. There may be differences in the importance of the exceptional conditions that are found, but there is never any plausible reason that could be given that the more important one will be found first or that NOT being able to throw one makes sense (it seldom does in any high availability/reliability system design). Even if two exceptional conditions are of equal importance or the more important gets thrown first, it does not seem to be very plausible that swallowing only the first makes much sense. Exceptions provide a control paradigm in for readily backing out of portions of call stacks that allows some disciplined use of call frames for data. But the current scheme seriously limits it useability. Certainly we do not want to go back to the "globals and heap only" approach necessitated by a setjump/longjump approach. But the current scheme is almost as distorting of design by forcing a one at a time design and not giving any good means of insuring that any libraries used will gracefully fit into that. Yet it forces them to be used. The door has been opened, but now you have to go all the way through. > PROPOSAL: Allow Multiple Simultaneous Exceptions [ An inadequate proposal is deleted ] I like the sentiment, but the details don't make the grade. First the possible multiple exceptional condition cases need to be more accurately delineated. Then the handler cases need to be matched up with them. First, there may be unrelated exceptional conditions that occur in the same window (window meaning additional conditions need to be detected and raised before some other condition has been handled). Second, there may be similar but distinct exceptional conditions that occur in the same window. Third, there may be separate detections of a common exceptional condition. Each of these may have its own needs. In the third case, it may be much easier to write software if you could say something to the effect of "throw this if it is not already thrown." Obviously, determining the identity for "already thrown" is the key issue. But here the needs are on the throw side. In the second case, the exceptions need to be distinguishable at throw time yet are likely to need handling by the same handler or sequence of handlers as you unfold. Here, the handler may successfully handle one subset and need the throw a remaining subset. Some may even fit part of the first case as discussed below. In the first case, you have two kinds of handler situations: single handlers that handle unrelated exceptional conditions and cascades of handlers that handle various subsets of them, both of these having the potential of successfully handling subsets and rethrowing other subsets. The order of looking at the exceptional conditions may matter. [cascade is used in the sense of multiple catches for a try.] These are the static cases. That is, these are the cases where the appilcation exception handling is fixed at compile time. I bring this up as a distinction as I also see a possible need for runtime exception handling binding. However, compared to the static case this is a frill where a good solution for the static case is a necessity. A library may want to establish base level handling of its exceptions at the outer call layer to insure that basic handling will happen if the calling application does none. This would force the unwinding of the call frames, which may be important to the library's provided service, and would then allow the basic exception code specified by the library to be called at the tail end. This is dynamic in the sense that the library may need to establish this when called, particularly if the linkage to it is created at runtime with use then distributed. If the application does "handle" the exceptional condition, the library can get notified via the destructor call for the exception instance and it may need to rethrow if it was not really handled. So, I tried here to outline the real problem as I see it. I feel that much of the squirming going on now with respect to exceptions is because the current mechanism in woefully inadequate in fundamental ways. The rest, of course, is due to partial shock at the implications of really dealing with exceptional conditions and partial denial in most people's design and code. An amazing amount of code never checks for errors since that would "distort" the design too much. Taking a major part of that distortion away is what the exception control paradigm should do (making this excuse as lame as feasible), but it has to solve the full problem to be truly useable. Good Day Dick Dick.Menninger@DaytonOH.ATTGIS.COM [ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu. Contact address: std-c++-request@ncar.ucar.edu. The moderation policy is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads