Re: Controlled types and exception safety



"Dmitry A. Kazakov" <mailbox@xxxxxxxxxxxxxxxxx> wrote in message
news:c5f58jf7dlvo.jwmx6q1b5l24$.dlg@xxxxxxxxxxxxx
> On Thu, 01 Dec 2005 11:46:42 +0100, Maciej Sobczak wrote:
....
> > This changes a lot. I *know* how to deal with exceptions in
> > constructors, especially if their only effect is to build structures in
> > memory (and that applies to Stack in particular). Note that when the
> > constructor throws/raises, the object is considered to be never created
> > and its destructor is therefore never called.
>
> I.e. whatever side effects the failed constructor has caused, they will
> persist. The problem is not in finalization of the target. The problem is
> in the system state = whether objects invariants hold between their
> construction and finalization.

Right. Such a constructor ought to clean up its mess before propagating an
exception. If it doesn't, you'll have memory leaks and other such badness.

> [...]
> > What's wrong with the example I provided in my previous post?
> [...]
> > Which is exactly what is needed. If it fails, it can be rolled-back
> > without touching the original left object.
>
> As I said, in my view it has little to do with exception safety. What you
> actually wish is to have access to the left side of assignment. Controlled
> types do not provide this functionality. End of story.

Right again. Ada doesn't really have user-defined assignment; if you
*really* need that you have to use a procedure.

And in any case, what you are asking for would be contrary to the efficiency
goals of Ada. You're saying that all assignment *have to be* made to
temporaries. I can imagine some language working that way, but it's
performance would be several times slower than C++. We have enough trouble
with people thinking Ada is slow as it is, without duplicating all of the
effort twice. There is a lot of words in the Ada standard specifically to
allow implementers to optimize (eliminating the assignment temporary, for
instance).

Ada's model is that a failed assignment leaves the target corrupt. You can
mitigate that, but not completely eliminate it. If that is unacceptable for
your application (and I can think of few for which that would be the case),
then you have to avoid ":=" (most likely by using a limited type). At least
Ada 200Y improves the support for limited types a lot, so that you no longer
have to give up fancy constructors, aggregates, and constants when you use
them.

In your example of a failed stack assignment, the Adjust routine ought to
clean up the mess if Storage_Error is raised, and leave the target Stack
empty. Is this ideal? Possibily not, but it hardly matters, because there is
no clean way to know what might or might not have been done when the
assignment fails (read 11.6 if you believe otherwise); recovery means
exiting out and rolling back far more than one object. (And there really is
no safe, portable recovery from out-of-memory conditions -- you can only
figure out what works with a specific compiler and target and do that.)

....
> > The difficult part is that in *all* cases that I've seen or written (in
> > C++), it was not possible to guarantee that the duplication of state can
> > be performed without errors. This certainly applies to all types that
> > have dynamic memory structures behind them, starting from innocent
> > unbounded string. Ada has unbounded string, recommended on this group in
> > various contexts. How does it dolve this problem? Does it?
>
> I think Randy has answered that.

Probably not specifically. Obviously it depends on the implementation. I
just looked at ours, and it does nothing at all to handle memory issues in
Adjust. That means that the object would fail the invariants after such an
assignment. (I didn't actually realize that; it would be better to null the
pointer in that case...) And presumably, it would eventually access through
a deallocated pointer. But that's all a correct (if unfriendly)
implementation of Ada, because the object is abnormal, and any access to it
is erroneous -- see 13.9.1. (Humm, this actually isn't as clear as it ought
to be; one could argue that Storage_Error isn't a "language-defined check"
(its not called that in 11.1(6)). But surely it is intended to be covered;
it's hard to imagine a case that is more likely to corrupt things than
running out of memory. And it is indexed as a check. So I apply Dewar's rule
[the Standard never says anything silly]. Anyway, sorry about the language
lawyer musings...)

Moral: don't touch the left-hand side of any assignment after it failed
raising an exception, other than to assign a new value to the *entire*
value. If you want some other semantics, don't fool yourself and others by
calling it ":="; use limited types and appropriate copying procedures.

Randy.



.



Relevant Pages

  • Re: Controlled types and exception safety
    ... Now you are sitting in a rocket, a user-defined constructor has just turned on the ignition, and oops, you notice that you have left your hat at home... ... the Adjust started to duplicate the structure and it notices that there is not enough memory to do this... ... The point is that this new object is *separate* from the destination object (from what's on the left side of assignment operator), ...
    (comp.lang.ada)
  • Re: Memory leak - What the ...?
    ... > user-defined assignment has access to both the object being assigned ... In Ada, if the identity ... It is an easy mistake to forget the copy constructor or assignment ... default initialise and assignment operator will keep the old value. ...
    (comp.lang.ada)
  • Re: WaitForSingleObject() will not deadlock
    ... the line commented out, and assuming there is no other gratuitous assignment to x, then it ... A memory address is a memory address. ... that is awakened by that signal or broadcast. ... even if it occurs before it awakens. ...
    (microsoft.public.vc.mfc)
  • Re: Readings on clr optimization?
    ... The compiler cannot inline a call to a constructor if the class has a static ... Weak references are special objects that allow you to track references that ... There aren't many implication with memory ...
    (microsoft.public.dotnet.framework.clr)
  • Re: Readings on clr optimization?
    ... Funny...Those are my 3 favorite advanced .Net books! ... The compiler cannot inline a call to a constructor if the class has a static ... Weak references are special objects that allow you to track references that ... There aren't many implication with memory ...
    (microsoft.public.dotnet.framework.clr)