comp.lang.ada
 help / color / mirror / Atom feed
* Allocators and exceptions
@ 2007-09-09  7:40 Maciej Sobczak
  2007-09-09 12:17 ` anon
                   ` (4 more replies)
  0 siblings, 5 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-09  7:40 UTC (permalink / raw)


What happens when during the initialization of the newly allocated
object an exception is raised?

I cannot find anything in the AARM that covers this case. What I want
to find exactly is the *guarantee* that the allocated memory is
automatically reclaimed.
Any relevant paragraph numbers are highly welcome.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09  7:40 Allocators and exceptions Maciej Sobczak
@ 2007-09-09 12:17 ` anon
  2007-09-09 20:31   ` Maciej Sobczak
  2007-09-10 10:37 ` Allocators and exceptions => Read Me First anon
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 55+ messages in thread
From: anon @ 2007-09-09 12:17 UTC (permalink / raw)


For deallocation

Recheck RM 13.11.2 Unchecked Storage Deallocation

       Paragragh (10) suggest that deallocation is guarantee, with
       the exception if the object is a Task (9).

       Also, no system defined exception raised on Deallocation.

See System.Memory for routines on how GNAT Ada defines the core 
Allocation, Deallocation, and Reallocation routines.

For some other insight you might want to look at Chapter 21: 
"Memory Management Issues" of the "Gnat User Guide". It does 
talk about problems in deallocation and provides informaton to 
check for errors.


In <1189323618.588340.87180@o80g2000hse.googlegroups.com>,  Maciej Sobczak <see.my.homepage@gmail.com> writes:
>What happens when during the initialization of the newly allocated
>object an exception is raised?
>
>I cannot find anything in the AARM that covers this case. What I want
>to find exactly is the *guarantee* that the allocated memory is
>automatically reclaimed.
>Any relevant paragraph numbers are highly welcome.
>
>--
>Maciej Sobczak
>http://www.msobczak.com/
>




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09 12:17 ` anon
@ 2007-09-09 20:31   ` Maciej Sobczak
  2007-09-09 22:43     ` Simon Wright
                       ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-09 20:31 UTC (permalink / raw)


On 9 Wrz, 14:17, a...@anon.org (anon) wrote:
> For deallocation
>
> Recheck RM 13.11.2 Unchecked Storage Deallocation
>
>        Paragragh (10) suggest that deallocation is guarantee, with
>        the exception if the object is a Task (9).

You probably misunderstood me. I'm asking what will happen when the
exception is raised when the allocator is evaluated.
Consider:

procedure P is

   type T (Init : Integer) is record
      C : Positive := Positive (Init);
   end record;

   type T_Access is access T;

   Ptr : T_Access;

begin
   Ptr := new T (-5);
exception
   when Constraint_Error =>
      -- is memory leaked or deallocated?
      null;
end;

I want to know whether the memory that was allocated for the new
object was immediately deallocated due to the exception.
By "immediately" I mean before the control even goes to the exception
part.

I don't find this guarantee anywhere in the AARM and it scares me.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09 20:31   ` Maciej Sobczak
@ 2007-09-09 22:43     ` Simon Wright
  2007-09-10 12:10       ` Maciej Sobczak
  2007-09-10  2:56     ` anon
  2007-09-10 12:42     ` Dmitry A. Kazakov
  2 siblings, 1 reply; 55+ messages in thread
From: Simon Wright @ 2007-09-09 22:43 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> procedure P is
>
>    type T (Init : Integer) is record
>       C : Positive := Positive (Init);
>    end record;
>
>    type T_Access is access T;
>
>    Ptr : T_Access;
>
> begin
>    Ptr := new T (-5);
> exception
>    when Constraint_Error =>
>       -- is memory leaked or deallocated?
>       null;
> end;
>
> I want to know whether the memory that was allocated for the new
> object was immediately deallocated due to the exception.  By
> "immediately" I mean before the control even goes to the exception
> part.
>
> I don't find this guarantee anywhere in the AARM and it scares me.

I'm not sure that I'd be scared, precisely.

If this was a safety-related program I would expect some serious test
effort, which would probably discover the mistake; or maybe formal
methods would be appropriate.

Even then, a safety-related _system_ ought to have some strategy for
recovering from such a runtime error. Perhaps it should reboot into a
safe mode? I would certainly expect the processor running a car's
ignition system not to just give up on an unhandled exception ...

In any case, why would the runtime system need to guarantee memory
recovery when it can hardly be expected to recover from the failed
design that led to the situation in the first place? I don't believe
there's any sensible recovery action to be taken -- the program's
state is corrupt already. Reboot, you know it makes sense!



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09 20:31   ` Maciej Sobczak
  2007-09-09 22:43     ` Simon Wright
@ 2007-09-10  2:56     ` anon
  2007-09-10 12:42     ` Dmitry A. Kazakov
  2 siblings, 0 replies; 55+ messages in thread
From: anon @ 2007-09-10  2:56 UTC (permalink / raw)


May be this will answer you question in a little more deal.

This is mainly an operating system or an operating environment routines 
question that deal with the "HEAP" and not for the RM. From the links 
in System.Memory:

   function c_malloc (Size : size_t) return System.Address;
   pragma Import (C, c_malloc, "malloc");

and

   function c_realloc
     (Ptr : System.Address; Size : size_t) return System.Address;
   pragma Import (C, c_realloc, "realloc");

either the "malloc" or "realloc" will normally return a pointer to the 
memory if and only if the complete block being allocation is available in 
the heap. But if less than requested size is available then the routines 
just returns a "NULL" denoting a error condition, and the Ada routine 
raises an Storage_Error with information about the heap being exhausted. 
Also the remaining unattracted heap memory is still there.

An Example:

  with Ada.Text_IO ;
  --
  -- If the Heap is set to 128 bytes.
  --
  procedure test is 

    type szp is access string ;

    name : szp ;

  begin 
    Ada.Text_IO.Put_Line ( "Heap Size = 128" )  ;
    --
    -- Then this code will raise the Storage_Error
    --
    begin
     name := new String ( 1..256 ) ;
    exception
       when Storage_Error =>
         Ada.Text_IO.Put_Line ( "Storage Error, 256" )  ;
    end ;
    --
    -- This code will allocate the memory and assign it to "name"
    --
    begin
     name := new String ( 1..100 ) ;
    exception
       when Storage_Error =>
         Ada.Text_IO.Put_Line ( "Storage Error, 100" )  ;
    end ;
   --
   -- Heap should have a size of 28 bytes
   --
   Ada.Text_IO.Put_Line ( "Heap Size = 28" )  ;
  end ;


In <1189369871.672082.162750@50g2000hsm.googlegroups.com>,  Maciej Sobczak <see.my.homepage@gmail.com> writes:
>On 9 Wrz, 14:17, a...@anon.org (anon) wrote:
>> For deallocation
>>
>> Recheck RM 13.11.2 Unchecked Storage Deallocation
>>
>>        Paragragh (10) suggest that deallocation is guarantee, with
>>        the exception if the object is a Task (9).
>
>You probably misunderstood me. I'm asking what will happen when the
>exception is raised when the allocator is evaluated.
>Consider:
>
>procedure P is
>
>   type T (Init : Integer) is record
>      C : Positive := Positive (Init);
>   end record;
>
>   type T_Access is access T;
>
>   Ptr : T_Access;
>
>begin
>   Ptr := new T (-5);
>exception
>   when Constraint_Error =>
>      -- is memory leaked or deallocated?
>      null;
>end;
>
>I want to know whether the memory that was allocated for the new
>object was immediately deallocated due to the exception.
>By "immediately" I mean before the control even goes to the exception
>part.
>
>I don't find this guarantee anywhere in the AARM and it scares me.
>
>--
>Maciej Sobczak
>http://www.msobczak.com/
>




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions => Read Me First
  2007-09-09  7:40 Allocators and exceptions Maciej Sobczak
  2007-09-09 12:17 ` anon
@ 2007-09-10 10:37 ` anon
  2007-09-10 12:16   ` Maciej Sobczak
  2007-09-10 15:44 ` Allocators and exceptions Adam Beneschan
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 55+ messages in thread
From: anon @ 2007-09-10 10:37 UTC (permalink / raw)


It is there, but it is in a hard section to see. Took me a little time 
to find it. And you can discard the early post.

And no, it is not truly guarantee, but some compiler may reclain 
immediate during a raised exception.

But to Force it use:

        pragma Restrictions ( Immediate_Reclamation ) ;


Note: RM Annex H  => H.4 Safety and Security Restrictions



  pragma Restrictions ( Immediate_Reclamation ) ;

  with Ada.Text_IO ;
  with Ada.Integer_Text_IO ;
  --
  procedure test is 

    type ap is access positive ;

    Value : ap ;
    Minus5 : integer := -5 ;

  begin 
    --
    -- FIRST: name is give a location and initial value
    --
    Value := new Positive'( 512 );

    Ada.Text_IO.Put_Line ( "Inital" )  ;
    Ada.Text_IO.Put ( "  Value = " )  ;
    Ada.Integer_Text_IO.Put ( Value.all ) ;
    Ada.Text_IO.New_Line ;

    begin
      Value := new Positive'( Minus5 ) ;

      Ada.Text_IO.Put_Line ( "Value = a new constant" )  ;
    exception
       when Storage_Error =>
         Ada.Text_IO.Put_Line ( "Storage Error" )  ;
       when Constraint_Error =>
         Ada.Text_IO.Put_Line ( "Constraint Error" )  ;
    end ;

    --
    -- The point Value is still points to a valid location 
    --
    Ada.Text_IO.Put ( "  Value = " )  ;
    Ada.Integer_Text_IO.Put ( Value.all ) ;
    Ada.Text_IO.New_Line ;

  end test ;


In <1189323618.588340.87180@o80g2000hse.googlegroups.com>,  Maciej Sobczak <see.my.homepage@gmail.com> writes:
>What happens when during the initialization of the newly allocated
>object an exception is raised?
>
>I cannot find anything in the AARM that covers this case. What I want
>to find exactly is the *guarantee* that the allocated memory is
>automatically reclaimed.
>Any relevant paragraph numbers are highly welcome.
>
>--
>Maciej Sobczak
>http://www.msobczak.com/
>




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09 22:43     ` Simon Wright
@ 2007-09-10 12:10       ` Maciej Sobczak
  2007-09-10 19:08         ` Simon Wright
  0 siblings, 1 reply; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-10 12:10 UTC (permalink / raw)


On 10 Wrz, 00:43, Simon Wright <simon.j.wri...@mac.com> wrote:

> I'm not sure that I'd be scared, precisely.
>
> If this was a safety-related program I would expect some serious test
> effort, which would probably discover the mistake; or maybe formal
> methods would be appropriate.

Sure. Or even better - forget about dynamic memory and solve these
problems by avoiding them.

> Even then, a safety-related _system_ ought to have some strategy for
> recovering from such a runtime error.

Of course - and imagine that it can recover from the error that caused
the exception. But the problem is with memory leak - how can you
recover from memory leak if you don't have any pointer to the memory
block that was already allocated?

> In any case, why would the runtime system need to guarantee memory
> recovery when it can hardly be expected to recover from the failed
> design that led to the situation in the first place?

Assume that it does recover from the failure that has led to the
exception.
How to recover from the resulting memory leak?

> I don't believe
> there's any sensible recovery action to be taken -- the program's
> state is corrupt already.

Why do you think it is necessarily corrupt?
Just reading to the end of the file causes an exception. Using a
network connection that got broken can cause an exception. In both
cases there is no corruption of the program state and reasonable
recovery (or graceful degradation of the functionality) can be
provided.
How to handle the memory leak?

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions => Read Me First
  2007-09-10 10:37 ` Allocators and exceptions => Read Me First anon
@ 2007-09-10 12:16   ` Maciej Sobczak
  2007-09-10 22:10     ` Allocators and exceptions => Trying Again anon
  0 siblings, 1 reply; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-10 12:16 UTC (permalink / raw)


On 10 Wrz, 12:37, a...@anon.org (anon) wrote:

>         pragma Restrictions ( Immediate_Reclamation ) ;

It does not apply to objects created by the allocator.

It is useful only for those objects that are created implicitly, for
example return values of unconstrained types.

My question still holds. And I'm still scared.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09 20:31   ` Maciej Sobczak
  2007-09-09 22:43     ` Simon Wright
  2007-09-10  2:56     ` anon
@ 2007-09-10 12:42     ` Dmitry A. Kazakov
  2007-09-10 21:48       ` Maciej Sobczak
  2 siblings, 1 reply; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-10 12:42 UTC (permalink / raw)


On Sun, 09 Sep 2007 13:31:11 -0700, Maciej Sobczak wrote:

> Consider:
> 
> procedure P is
> 
>    type T (Init : Integer) is record
>       C : Positive := Positive (Init);
>    end record;
> 
>    type T_Access is access T;
> 
>    Ptr : T_Access;
> 
> begin
>    Ptr := new T (-5);
> exception
>    when Constraint_Error =>
>       -- is memory leaked or deallocated?
>       null;
> end;
> 
> I want to know whether the memory that was allocated for the new
> object was immediately deallocated due to the exception.
> By "immediately" I mean before the control even goes to the exception
> part.
> 
> I don't find this guarantee anywhere in the AARM and it scares me.

The question is not only about deallocation, it is also about finalization
of the components initialized before the initialization raised an
exception. Components are initialized in an arbitrary order.

I cannot tell for sure, but I guess that your example is a bounded error.
Depending on the compiler the effect should be either Constraint_Error and
everything rolled back including memory allocation, or else it is
Program_Error + some mess.

But you should really ask a language lawyer.

P.S. Exceptions in constructors is a bad idea. Consider this:

   type T (Init : Integer) is record
      B : access Positive := new Positive;
      C : Positive := Positive (Init);
   end record;

   Ptr := new T (-5);

Now you might really want the compiler not to deallocate Ptr, so that you
were able to free Ptr.B before. But where do you know that B was
initialized?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09  7:40 Allocators and exceptions Maciej Sobczak
  2007-09-09 12:17 ` anon
  2007-09-10 10:37 ` Allocators and exceptions => Read Me First anon
@ 2007-09-10 15:44 ` Adam Beneschan
  2007-09-10 21:58   ` Maciej Sobczak
                     ` (2 more replies)
  2007-09-11  2:36 ` Randy Brukardt
  2007-09-12  3:08 ` Allocators and exceptions -- Debugging says memory leak! anon
  4 siblings, 3 replies; 55+ messages in thread
From: Adam Beneschan @ 2007-09-10 15:44 UTC (permalink / raw)


On Sep 9, 12:40 am, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> What happens when during the initialization of the newly allocated
> object an exception is raised?
>
> I cannot find anything in the AARM that covers this case. What I want
> to find exactly is the *guarantee* that the allocated memory is
> automatically reclaimed.
> Any relevant paragraph numbers are highly welcome.

I don't think this can be guaranteed, not as I read 4.8(10).  The
semantics of an allocator without an initializer is that the object is
created (that's the allocation), and then the components are
initialized.  If an exception raise occurs during the initialization
process, the object creation has already occurred, and there's nothing
that says that this is reversed.  In fact, I believe there is nowhere
in the language that says that memory is automatically reclaimed in
*any* situation; and, in fact, there is no guarantee that you can even
reclaim any storage at all.  13.11.2 defines Unchecked_Deallocation,
but this section has an "Implementation Advice" that says "For a
standard storage pool, Free [an instance of Unchecked_Deallocation]
should actually reclaim the storage."  Note that that is only
*advice*.  So an implementation can legitimately be an Ada compiler
without implementing Unchecked_Deallocation at all.  The message here,
I think, is that the Ada language has said that it doesn't worry about
storage reclamation; you have to worry about that yourself.

Anyway, if this is an issue, I'd write a function to perform the "new"
operation.  Using your later example:

   function new_T (Init : Integer) return T_Access is
   begin
      declare
         New_Rec : T (Init);
      begin
         return new T' (New_Rec);
      end;
   exception
      when others => ...
   end new_T;

Now any exceptions involved in initializing the record will get caught
before allocation takes place.  The allocator itself won't raise any
exceptions (other than Storage_Error), unless copying New_Rec to the
newly allocated object raises an exception, which could happen only if
there are controlled types involved and an Adjust routine raises an
exception, in which case you're in a whole bunch of trouble anyway.

                    -- Adam






^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-10 12:10       ` Maciej Sobczak
@ 2007-09-10 19:08         ` Simon Wright
  0 siblings, 0 replies; 55+ messages in thread
From: Simon Wright @ 2007-09-10 19:08 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

>> I don't believe
>> there's any sensible recovery action to be taken -- the program's
>> state is corrupt already.
>
> Why do you think it is necessarily corrupt?
> Just reading to the end of the file causes an exception. Using a
> network connection that got broken can cause an exception. In both
> cases there is no corruption of the program state and reasonable
> recovery (or graceful degradation of the functionality) can be
> provided.

In these cases I would agree (though I agree with Adam that you sould
read from the file before allocating memory for the result). Your
example, on the other hand, involved using -5 as an actual for a
Positive ...



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-10 12:42     ` Dmitry A. Kazakov
@ 2007-09-10 21:48       ` Maciej Sobczak
  2007-09-11  9:16         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-10 21:48 UTC (permalink / raw)


On 10 Wrz, 14:42, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> The question is not only about deallocation, it is also about finalization
> of the components initialized before the initialization raised an
> exception.

Right.

> Components are initialized in an arbitrary order.

Oops.

> I cannot tell for sure, but I guess that your example is a bounded error.

> But you should really ask a language lawyer.

I hoped that c.l.a. is a good place for this.

> > P.S. Exceptions in constructors is a bad idea.

No, it's a very good idea. Otherwise you have to deal with half-baked
objects, which is Even Bigger Mess (tm).

> Consider this:
>
>    type T (Init : Integer) is record
>       B : access Positive := new Positive;
>       C : Positive := Positive (Init);
>    end record;
>
>    Ptr := new T (-5);
>
> Now you might really want the compiler not to deallocate Ptr, so that you
> were able to free Ptr.B before. But where do you know that B was
> initialized?

It's not my business. The compiler knows for sure what what already
initialized and can therefore take the informed decision on what to
roll back.

I'm surprised by this issue. Really.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-10 15:44 ` Allocators and exceptions Adam Beneschan
@ 2007-09-10 21:58   ` Maciej Sobczak
  2007-09-10 22:07   ` Jeffrey R. Carter
  2007-09-11  9:14   ` Dmitry A. Kazakov
  2 siblings, 0 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-10 21:58 UTC (permalink / raw)


On 10 Wrz, 17:44, Adam Beneschan <a...@irvine.com> wrote:

> I don't think this can be guaranteed, not as I read 4.8(10).
[...]

> The message here,
> I think, is that the Ada language has said that it doesn't worry about
> storage reclamation; you have to worry about that yourself.

That's OK for me as long as I'm given necessary tools for this. The
problem is that with exceptions I cannot even be sure that I have the
access value. Without it "worrying about that myself" is at least
challenging.

> Anyway, if this is an issue, I'd write a function to perform the "new"
> operation.  Using your later example:
>
>    function new_T (Init : Integer) return T_Access is
>    begin
>       declare
>          New_Rec : T (Init);
>       begin
>          return new T' (New_Rec);
>       end;
>    exception
>       when others => ...
>    end new_T;

OK, so let's complicate it a bit - T is limited. :-)
I know that it can be hacked around. I just did not expect Ada to put
me in the position that would require hacking something around.

> Now any exceptions involved in initializing the record will get caught
> before allocation takes place.  The allocator itself won't raise any
> exceptions (other than Storage_Error), unless copying New_Rec to the
> newly allocated object raises an exception, which could happen only if
> there are controlled types involved and an Adjust routine raises an
> exception, in which case you're in a whole bunch of trouble anyway.

Yeah, that's my other disappointment in this area - assignment cannot
be made "atomic" in the transactional sense.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-10 15:44 ` Allocators and exceptions Adam Beneschan
  2007-09-10 21:58   ` Maciej Sobczak
@ 2007-09-10 22:07   ` Jeffrey R. Carter
  2007-09-11  9:14   ` Dmitry A. Kazakov
  2 siblings, 0 replies; 55+ messages in thread
From: Jeffrey R. Carter @ 2007-09-10 22:07 UTC (permalink / raw)


Adam Beneschan wrote:
> 
> In fact, I believe there is nowhere
> in the language that says that memory is automatically reclaimed in
> *any* situation; and, in fact, there is no guarantee that you can even
> reclaim any storage at all.  13.11.2 defines Unchecked_Deallocation,
> but this section has an "Implementation Advice" that says "For a
> standard storage pool, Free [an instance of Unchecked_Deallocation]
> should actually reclaim the storage."  Note that that is only
> *advice*.  So an implementation can legitimately be an Ada compiler
> without implementing Unchecked_Deallocation at all.

It has to implement Unchecked_Deallocation, and the implementation has 
to set the parameter X to null. But that's all an implementation has to 
do, and that's all the Rolm/Data General compiler did in 1984. But every 
more recent compiler that I've used actually did deallocation.

-- 
Jeff Carter
"It's all right, Taggart. Just a man and a horse being hung out there."
Blazing Saddles
34



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions => Trying Again
  2007-09-10 12:16   ` Maciej Sobczak
@ 2007-09-10 22:10     ` anon
  2007-09-10 23:15       ` Markus E L
  0 siblings, 1 reply; 55+ messages in thread
From: anon @ 2007-09-10 22:10 UTC (permalink / raw)


The Constraint_Error will not alter the memory allocation. The only 
exception that effect memory allocation is the system generated 
Storage_Error. No other exception will alter memory. Which 
denotes a memory leak.

Programmers can confuse the compiler that creates and allows memory 
leaked or unexplained deallocates.  And its not the languages fault but 
the programmers. This might explain why it is not defined directly in 
the RM.


The problem is that even though it is legal to have 

  type T (Init : Integer) is record
     C : Positive := Positive (Init);
  end record;
 
It does allows the concept of memory leaks to be introduce into a 
program. Some compile may use deallocation others may allow memory 
leaked, while other might do type checking first and generate the 
Constraint_Error before memory is allocate.

If you used, instead:

  type T (Init : Positive ) is record
     C : Positive := Init ;
  end record ;

then do the integer to positive conversion in the body like

-- Note:  Ptr := new T ( Positive ( -5 ) ); will generate a 
-- compiler warning, so

  C_Value : Constant Integer := -5 ;

  Ptr := new T ( Positive ( C_Value ) ) ;


In this design the conversion of the Integer to Positive will generate 
the exception, before the system trys to allocate any memory. Which 
Guarantees, when the exception will happen and the programmer can 
predict how the system will react, else there is no Guarantee.


For Memory Leaks: 

Read Chapter 21, of the "GNAT User Guide" it deals with 
memory leaks, with the use of debugging and "gnatmem". The 
example they use may not be like yours but in reading it 
you should be able to adapt the concept to your code.


In <1189426567.755739.178270@r29g2000hsg.googlegroups.com>,  Maciej Sobczak <see.my.homepage@gmail.com> writes:
>On 10 Wrz, 12:37, a...@anon.org (anon) wrote:
>
>>         pragma Restrictions ( Immediate_Reclamation ) ;
>
>It does not apply to objects created by the allocator.
>
>It is useful only for those objects that are created implicitly, for
>example return values of unconstrained types.
>
>My question still holds. And I'm still scared.
>
>--
>Maciej Sobczak
>http://www.msobczak.com/
>




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions => Trying Again
  2007-09-10 22:10     ` Allocators and exceptions => Trying Again anon
@ 2007-09-10 23:15       ` Markus E L
  0 siblings, 0 replies; 55+ messages in thread
From: Markus E L @ 2007-09-10 23:15 UTC (permalink / raw)



'anon AT anon DOT org (anon)' wrote:

> The Constraint_Error will not alter the memory allocation. The only 

Again our favourite TROLL SCRYER [tm] doesn't grok what this is all
about ...

> exception that effect memory allocation is the system generated 
> Storage_Error. No other exception will alter memory. Which 
> denotes a memory leak.


... but is still talking with the posture of an expert. 

Don't you get tired of this? In the meantime I've begun to doubt that
you have had more than superficial exposure to Ada.

- M





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-09  7:40 Allocators and exceptions Maciej Sobczak
                   ` (2 preceding siblings ...)
  2007-09-10 15:44 ` Allocators and exceptions Adam Beneschan
@ 2007-09-11  2:36 ` Randy Brukardt
  2007-09-11 15:33   ` Adam Beneschan
  2007-09-12  3:08 ` Allocators and exceptions -- Debugging says memory leak! anon
  4 siblings, 1 reply; 55+ messages in thread
From: Randy Brukardt @ 2007-09-11  2:36 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message
news:1189323618.588340.87180@o80g2000hse.googlegroups.com...
> What happens when during the initialization of the newly allocated
> object an exception is raised?
>
> I cannot find anything in the AARM that covers this case. What I want
> to find exactly is the *guarantee* that the allocated memory is
> automatically reclaimed.
> Any relevant paragraph numbers are highly welcome.

Amplifying Adam's response:

(1) Nothing in the Ada standard is about "goodness". In particular, there is
nothing anywhere in the standard that resources like memory ever get
reclaimed. I suspect most implementers will in fact do reclamation (and
avoid leaks), but it is not part of the Ada language as described by the
standard.

(2) I believe that the current wording of the standard *requires* that
reclamation *not* be performed in examples like this, at least if there are
any controlled components in the type. That's because there is no permission
in Ada to do finalization early - it has to be done only if the object is
explicitly destroyed or when the master goes out of scope -- which for an
allocated object is when the *type* goes out of scope.

(Not everyone agrees with the above opinion, but everyone does agree that it
is an issue in some cases. But there is nothing close to an agreement on how
to fix the standard, so don't hold your breath waiting for a fix...)

Yes, this also means that an Ada compiler implementing garbage collection is
mostly likely incorrect. It's highly unlikely, however, that anyone will be
testing for such "errors" formally. I did write an ACATS-style test for a
case like this and determined that most compilers do in fact finalization
the object at the appropriate time: which suggests that they leak memory in
this case.

Moral: Never, ever, write code that intentionally raises an exception during
an allocator. (Unintentional exceptions are just plain bugs and ought to get
fixed in testing.)  Better still, don't use any allocators at all (use the
predefined containers if you need dynamic memory management).

                                   Randy.


For what





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-10 15:44 ` Allocators and exceptions Adam Beneschan
  2007-09-10 21:58   ` Maciej Sobczak
  2007-09-10 22:07   ` Jeffrey R. Carter
@ 2007-09-11  9:14   ` Dmitry A. Kazakov
  2007-09-11  9:23     ` Maciej Sobczak
  2 siblings, 1 reply; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-11  9:14 UTC (permalink / raw)


On Mon, 10 Sep 2007 08:44:08 -0700, Adam Beneschan wrote:

> On Sep 9, 12:40 am, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
>> What happens when during the initialization of the newly allocated
>> object an exception is raised?
>>
>> I cannot find anything in the AARM that covers this case. What I want
>> to find exactly is the *guarantee* that the allocated memory is
>> automatically reclaimed.
> 
> I don't think this can be guaranteed, not as I read 4.8(10).

I think the wording Maciej used was wrong. He actually should say: 

For each Allocate called while execution of new, a matching Deallocate is
called with the same storage pool, address, size and alignment as they were
in the Allocate.

The ultimate effects of Allocate and Deallocate on the memory are
irrelevant.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-10 21:48       ` Maciej Sobczak
@ 2007-09-11  9:16         ` Dmitry A. Kazakov
  2007-09-11  9:19           ` Maciej Sobczak
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-11  9:16 UTC (permalink / raw)


On Mon, 10 Sep 2007 14:48:56 -0700, Maciej Sobczak wrote:

> On 10 Wrz, 14:42, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>> P.S. Exceptions in constructors is a bad idea.
> 
> No, it's a very good idea. Otherwise you have to deal with half-baked
> objects, which is Even Bigger Mess (tm).

This is what you get when the exception is propagated out of a constructor.
It breaks the abstraction, necessarily. You cannot handle this unless you
accept the idea that one can always view an object as an aggregate of other
objects. This in turn would imply 1) types matched by structure, 2) broken
encapsulation. You want the compiler to invent partial
constructors/destructors, it is a difficult problem, probably undecidable.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11  9:16         ` Dmitry A. Kazakov
@ 2007-09-11  9:19           ` Maciej Sobczak
  2007-09-11 12:27             ` Dmitry A. Kazakov
  2007-09-12 12:29             ` Stephen Leake
  0 siblings, 2 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-11  9:19 UTC (permalink / raw)


On 11 Wrz, 11:16, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> >>> P.S. Exceptions in constructors is a bad idea.
>
> > No, it's a very good idea. Otherwise you have to deal with half-baked
> > objects, which is Even Bigger Mess (tm).
>
> This is what you get when the exception is propagated out of a constructor.

In this case I want the constructor to be rolled back.
Without exceptions (and rollback) the only option for handling errors
in initialization of (sub)components is to leave them half-baked.

When I create a new object and there is some error on the way, I want
to consider the object as if it never existed.
This is what allows me to keep abstractions and invariants: either I
have the complete object with its guaranteed invariants, or there is
nothing. Anything in between is mess.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11  9:14   ` Dmitry A. Kazakov
@ 2007-09-11  9:23     ` Maciej Sobczak
  0 siblings, 0 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-11  9:23 UTC (permalink / raw)


On 11 Wrz, 11:14, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> I think the wording Maciej used was wrong. He actually should say:
>
> For each Allocate called while execution of new, a matching Deallocate is
> called with the same storage pool, address, size and alignment as they were
> in the Allocate.

Bingo.

However, to complete the picture, the components that were already
initialized and might require finalization should be finalized.

> The ultimate effects of Allocate and Deallocate on the memory are
> irrelevant.

Right. Even if the compiler does not guarantee the reclamation in
standard pool, I can provide my own with my own guarantees. The point
is to hook the appropriate calls.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11  9:19           ` Maciej Sobczak
@ 2007-09-11 12:27             ` Dmitry A. Kazakov
  2007-09-11 19:07               ` Maciej Sobczak
  2007-09-12 12:29             ` Stephen Leake
  1 sibling, 1 reply; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-11 12:27 UTC (permalink / raw)


On Tue, 11 Sep 2007 02:19:37 -0700, Maciej Sobczak wrote:

> On 11 Wrz, 11:16, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>>>> P.S. Exceptions in constructors is a bad idea.
>>
>>> No, it's a very good idea. Otherwise you have to deal with half-baked
>>> objects, which is Even Bigger Mess (tm).
>>
>> This is what you get when the exception is propagated out of a constructor.
> 
> In this case I want the constructor to be rolled back.
> Without exceptions (and rollback) the only option for handling errors
> in initialization of (sub)components is to leave them half-baked.

> When I create a new object and there is some error on the way, I want
> to consider the object as if it never existed.

This error is likely unrecoverable, so you have to reconsider your design
which allowed such errors.

BTW, formally everything is exactly as you wished! Observe, that

   new T(-5)

creates an object of the type T_Access. This object does not come to
existence and the compiler carefully eliminates any traces of this object.
Everything is fine!

What you actually want, but didn't say it, is that T_Access would take care
of the things it points to, so its constructor (new) would. That is not
what access types in Ada can. You want abstract access types. And this is
the core of the problem. Ada does not have abstract interfaces for built-in
types, alas.

> This is what allows me to keep abstractions and invariants: either I
> have the complete object with its guaranteed invariants, or there is
> nothing. Anything in between is mess.

This is violated upon aggregation of initialized components with side
effects. I don't argue that this is good, I only state that this is the
current language design and that it would be quite challenging to alter.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11  2:36 ` Randy Brukardt
@ 2007-09-11 15:33   ` Adam Beneschan
  2007-09-11 19:21     ` Maciej Sobczak
  2007-09-11 21:56     ` Adam Beneschan
  0 siblings, 2 replies; 55+ messages in thread
From: Adam Beneschan @ 2007-09-11 15:33 UTC (permalink / raw)


On Sep 10, 7:36 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

> (2) I believe that the current wording of the standard *requires* that
> reclamation *not* be performed in examples like this, at least if there are
> any controlled components in the type. That's because there is no permission
> in Ada to do finalization early - it has to be done only if the object is
> explicitly destroyed or when the master goes out of scope -- which for an
> allocated object is when the *type* goes out of scope.

It sure seemed to me that one could create an example in which, due to
a default initialization on a component that contains a function call
that does some interesting stuff, the automatic reclamation Maciej is
asking for would lead to a dangling reference or something just as
bad.  I wasn't able to create an example, but I didn't spend much time
on it.  Maybe something involving a self-pointer in a limited record
(just to tie it into another thread!).  I didn't try anything
involving controlled components.  But I'm still guessing that someone
could come up with an example that shows that this idea won't work.

                    -- Adam





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 12:27             ` Dmitry A. Kazakov
@ 2007-09-11 19:07               ` Maciej Sobczak
  2007-09-11 22:56                 ` Georg Bauhaus
  2007-09-12  9:32                 ` Dmitry A. Kazakov
  0 siblings, 2 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-11 19:07 UTC (permalink / raw)


On 11 Wrz, 14:27, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> This error is likely unrecoverable, so you have to reconsider your design
> which allowed such errors.

I disagree. The error might be unrecoverable (like broken network
cable), but might as well be worth retrying with modified parameters
(like wrong credentials were provided by the user).
Even in unrecoverable case I might want to gracefully reduce the
functionality of the system. Sorry, there will be no music today, but
please enjoy the party anyway - this sort of thing.

If we assume that the exception is an unconditional indication of
wrong design, then we might as well drop exceptions from the language
altogether.

> BTW, formally everything is exactly as you wished! Observe, that
>
>    new T(-5)
>
> creates an object of the type T_Access. This object does not come to
> existence and the compiler carefully eliminates any traces of this object.
> Everything is fine!

Except of the memory leak and the already created other components.

> What you actually want, but didn't say it, is that T_Access would take care
> of the things it points to, so its constructor (new) would.

No. T_Access is not (yet) involved. This has to be handled entirely by
the allocator, because the whole problem happens even before T_Access
is assigned to my access variable.

> > This is what allows me to keep abstractions and invariants: either I
> > have the complete object with its guaranteed invariants, or there is
> > nothing. Anything in between is mess.
>
> This is violated upon aggregation of initialized components with side
> effects. I don't argue that this is good, I only state that this is the
> current language design and that it would be quite challenging to alter.

I understand that it cannot be changed. At least not shortly after the
last standardization iteration. :-)

But... did I mention that C++ handles this issue correctly? ;-)
And no, it does not have any super-capable access types. A little bit
smarter allocator is enough.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 15:33   ` Adam Beneschan
@ 2007-09-11 19:21     ` Maciej Sobczak
  2007-09-11 21:56     ` Adam Beneschan
  1 sibling, 0 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-11 19:21 UTC (permalink / raw)


On 11 Wrz, 17:33, Adam Beneschan <a...@irvine.com> wrote:

> It sure seemed to me that one could create an example in which, due to
> a default initialization on a component that contains a function call
> that does some interesting stuff, the automatic reclamation Maciej is
> asking for would lead to a dangling reference or something just as
> bad.

No, there is no such risk. The object that failed to initialized
simply does not exist.

> Maybe something involving a self-pointer in a limited record
> (just to tie it into another thread!).

This limited record does not exist. Its presumably dangling self-
pointer does not exist, neither.
The access to the would-be object is never exposed out of the
allocator, so there is no way for anybody else to get the dangling
pointer.

The possible scenario where it could break could for example involve
the pool: the allocator calls Allocate on the pool and there the pool
registers the access value somewhere; then the initialization fails,
leading to roll-back that includes the call to Deallocate on the same
pool. The pool reclaims memory without unregistering the previously
exposed access value, leading to dangling pointer.

But this is not the problem of the discussed scheme, but rather the
problem of the pool - the same problem would happen with regular new
+Unchecked_Deallocation.

> But I'm still guessing that someone
> could come up with an example that shows that this idea won't work.

For your information, C++ works like that for as long as it has
operator new. If you come up with an example showing that this idea
doesn't work and it's not due to artificially broken environment, I
will ask you to share your findings widely.

Please show me a scheme where the idea breaks, but at the same time
where regular new+Unchecked_Deallocation doesn't.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 15:33   ` Adam Beneschan
  2007-09-11 19:21     ` Maciej Sobczak
@ 2007-09-11 21:56     ` Adam Beneschan
  2007-09-12  0:34       ` Jeffrey R. Carter
  2007-09-12 12:22       ` Maciej Sobczak
  1 sibling, 2 replies; 55+ messages in thread
From: Adam Beneschan @ 2007-09-11 21:56 UTC (permalink / raw)



On Sep 11, 8:33 am, I wrote:
> On Sep 10, 7:36 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>
> > (2) I believe that the current wording of the standard *requires* that
> > reclamation *not* be performed in examples like this, at least if there are
> > any controlled components in the type. That's because there is no permission
> > in Ada to do finalization early - it has to be done only if the object is
> > explicitly destroyed or when the master goes out of scope -- which for an
> > allocated object is when the *type* goes out of scope.
>
> It sure seemed to me that one could create an example in which, due to
> a default initialization on a component that contains a function call
> that does some interesting stuff, the automatic reclamation Maciej is
> asking for would lead to a dangling reference or something just as
> bad.

OK, I think I have one.  GNAT compiles and runs it, although I haven't
checked the language rules carefully to make sure it's legal.

----------------------------------------------------------------------------
package Pak1 is
    type Rec1 is limited private;
    type Rec1_Acc is access all Rec1;
    function Func1 (R : Rec1_Acc) return Integer;
private
    type Rec1 is limited record
        F1 : Integer := 123;
        F2 : Integer := Func1 (Rec1'Unchecked_Access);
    end record;
end Pak1;

package body Pak1 is

    P : Rec1_Acc;

    function Func1 (R : Rec1_Acc) return Integer is
    begin
        P := R;
        if R.F1 > 100 then
            raise Constraint_Error;
        end if;
        return 1;
    end Func1;

end Pak1;

with Pak1;
procedure test84 is
    X : Pak1.Rec1_Acc := new Pak1.Rec1;
begin
    null;
end test84;
----------------------------------------------------------------------------

When the allocator "new Pak1.Rec1" is evaluated, an object of type
Rec1 is created; then F1 is set to 123; then the code attempts to
initialize F2 by calling Func1.  The parameter is the
'Unchecked_Access of the object that has already been created.  Func1
saves this in the global P.  Then it raises Constraint_Error.  If the
Constraint_Error caused the object of type Rec1 to be deallocated and
thus no longer exist, P would then be left as a dangling reference.

                     -- Adam




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 19:07               ` Maciej Sobczak
@ 2007-09-11 22:56                 ` Georg Bauhaus
  2007-09-12 12:36                   ` Maciej Sobczak
  2007-09-12  9:32                 ` Dmitry A. Kazakov
  1 sibling, 1 reply; 55+ messages in thread
From: Georg Bauhaus @ 2007-09-11 22:56 UTC (permalink / raw)


On Tue, 2007-09-11 at 12:07 -0700, Maciej Sobczak wrote:

> But... did I mention that C++ handles this issue correctly? ;-)
> And no, it does not have any super-capable access types. A little bit
> smarter allocator is enough.

C++ doesn't seem to handle deallocation etc. of sibling components
either, so I'm not sure I understand. Isn't this a rather special
case you are describing?
 Should the following be excluded from consideration? (The program
quickly claims all available memory, as I would have expected; any
pointers to what should I read to learn how this can be simply
prevented in C++?)


class T {
   int c;
   int *x;
public:
   T(int init) {
      x = new int[1024];
      if (init < 1) { throw "Constraint_Error"; }
      c = init;
   }
   ~T() {
      delete[] x;
   }
};

typedef T* T_access;

int main()
{
   T_access ptr;

   while (1) {
      try {
         ptr = new T(-5); 
         delete ptr;
      } catch (...) {
         // all is well?
      }
   }
   return 0;
}





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 21:56     ` Adam Beneschan
@ 2007-09-12  0:34       ` Jeffrey R. Carter
  2007-09-12 12:13         ` Maciej Sobczak
  2007-09-12 12:22       ` Maciej Sobczak
  1 sibling, 1 reply; 55+ messages in thread
From: Jeffrey R. Carter @ 2007-09-12  0:34 UTC (permalink / raw)


Adam Beneschan wrote:
> 
> OK, I think I have one.  GNAT compiles and runs it, although I haven't
> checked the language rules carefully to make sure it's legal.

It looks legal to me. I've added a little test to see what's happening 
with P:

package Pak1 is
    type Rec1 is limited private;
    type Rec1_Acc is access all Rec1;

    function Func1 (R : Rec1_Acc) return Integer;

    procedure Check_P;
private
    type Rec1 is limited record
       F1 : Integer := 123;
       F2 : Integer := Func1 (Rec1'Unchecked_Access);
    end record;
end Pak1;

with Ada.Text_IO;

package body Pak1 is
    P : Rec1_Acc;

    function Func1 (R : Rec1_Acc) return Integer is
    begin
       P := R;
       if R.F1 > 100 then
          raise Constraint_Error;
       end if;
       return 1;
    end Func1;

    procedure Check_P is
       -- null;
    begin -- Check_P
       Ada.Text_IO.Put_Line
          (Item => "P = null => " & Boolean'Image (P = null) );

       if P /= null then
          Ada.Text_IO.Put_Line (Item => Integer'Image (P.F1) );
       end if;
    end Check_P;
end Pak1;

with Pak1;
procedure Test84 is
    -- null;
begin
    Create : declare
       X : Pak1.Rec1_Acc := new Pak1.Rec1;
    begin -- Create
       null;
    end Create;
exception -- Test84
when others =>
    Pak1.Check_P;
end Test84;

and get output:

P = null => FALSE
  123

I suppose P could be dangling, with the memory it points to not yet 
reused, but I suspect that is not the case.

-- 
Jeff Carter
"C++ is like jamming a helicopter inside a Miata
and expecting some sort of improvement."
Drew Olbrich
51



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions -- Debugging says memory leak!
  2007-09-09  7:40 Allocators and exceptions Maciej Sobczak
                   ` (3 preceding siblings ...)
  2007-09-11  2:36 ` Randy Brukardt
@ 2007-09-12  3:08 ` anon
  4 siblings, 0 replies; 55+ messages in thread
From: anon @ 2007-09-12  3:08 UTC (permalink / raw)


--
-- Dmitry A. Kazakov suggested in his first post that it was not 
-- only deallocation but finalization.  And in his second post he 
-- re-stated.  But does it the answer for your question.
--
-- For each call to allocation there is a finalization call as well.
--
-- And as you first stated, the answer was not in the AARM. but 
-- allocation with finalization are in the AARM. Now, the AARM also 
-- defines a user accessible hooks for each to allow the user 
-- to monitor these processes and to perform any additional action 
-- if it is needed.
--
-- The following examples are a modified examples of yours. So
-- why are the hooks procedures, not called as Dmitry A. Kazakov 
-- and Ada topic on finalization suggest?
--
-- Now as I suggested in my second post it is an operating 
-- environment in this case a compiler question. 
--
-- How is the statement 
--
--   Ptr := new T (-5);
--
-- evaluate and executed.
--
-- Does the statement first create the record. 
-- Then perform checks on the constant "-5" as the system trys to 
-- assign the value to the record variable C. 
-- If this is the case then a finalization has to take place after 
-- Constraint_Error.
--
-- Or does it perform the checks first.  
-- And because of the raised Constraint_Error the system will 
-- never allocate the memory for the new record. 
-- Which means no finalization is need.
--
-- Denoting its not an allocation, deallocation or finalization 
-- problem but a problem on how Ada and its compilers evaluate a 
-- statement and generate its machine code. This can lead to 
-- memory leaks, which is shown to be true in the example PZ.adb.
-- But this can be manage by altering the program code.
--
--

-- The following package is used to provide finalization hooks
-- used in the examples programs. They only show the hooks are
-- called by display a message.
--
--
-- P1.ads
--
with Ada.Finalization ; 
use  Ada.Finalization ;

package P1 is

   type T ( Init : Integer ) is new Controlled with record
      C : Positive := Positive ( Init ) ;
   end record ;

private

   procedure Initialize ( X : in out T ) ;
   procedure Adjust ( X : in out T ) ;
   procedure Finalize ( X : in out T ) ;

end P1 ;

--
-- P1.adb 
--
with Ada.Text_IO ; 
use  Ada.Text_IO ;

package body P1 is

  procedure Initialize ( X : in out T ) is

   begin
      Put_Line ( "Initialize called." ) ;
   end Initialize ;

  procedure Adjust ( X : in out T ) is

   begin
      Put_Line ( "Adjust called." ) ;
   end Adjust ;

  procedure Finalize ( X : in out T ) is

   begin
      Put_Line ( "Finalize called." ) ;
   end Finalize ;

end P1 ;

-- The following example is modified version of the original 
-- program, that uses the finalization hooks. 
--
-- In executing the program P0, The routine shows that it will 
-- raise Constraint_Error and no allocation or finalization will be 
-- preformed. But if you alter the constant "-5" to a "5". then 
-- finalization hooks will be performed. This also means that the 
-- Constraint_Error has nothing to with the memory allocation or 
-- possible memory leaks.
--
--
-- P0.adb
--
with P1 ;
use  P1 ;

with Ada.Text_IO ;
with Ada.Integer_Text_IO ;

procedure P0 is

   type T_Access is access T;

   Ptr : T_Access;

begin
   Ptr := new T (-5);

   Ada.Integer_Text_IO.Put ( Ptr.all.C ) ;
   Ada.Text_IO.New_Line ;
exception
   when Constraint_Error =>
      -- is memory leaked or deallocated?
      Ada.Text_IO.Put_Line ( "Constraint_Error" ) ;
      null;
end P0 ;


--
-- But does P0, allow memory leaks!
--
-- First, All Ada version should have debugging routines that 
-- the programmer can use to see this.
-- I use GNAT.Debug_Pools.
--
-- This Code shows that there are Memory Leaks in the statement 
--
--   Ptr := new T (-5);  
--
-- The info routine stated in the Constraint_Error block that
-- memory as been allocated but not deallocated in the old 
-- algorithm. Since, the Finalization is never called, this 
-- suggest Memory Leak! And without finalization hooks being 
-- called the program can not reclaim the memory, aka Memory Leak!
--
-- This suggest that the programmer should alter the program 
-- code to force the checking and possible Constraint_Error to 
-- a predictable part of the code that does not require memory 
-- or allow a Memory Leaks!
--
-- which I did in the new algorithm.
--

--
--
-- PZ.adb
--
with P1 ;
use  P1 ;

with Ada.Text_IO ;
with Ada.Integer_Text_IO ;

with GNAT.debug_pools ;
use  GNAT.debug_pools ;
with Ada.Exceptions ;
use  Ada.Exceptions ;

procedure PZ is


  type T_Access is access T;

  --
  -- Debug routine code
  --
  P : GNAT.Debug_Pools.Debug_Pool;
  for T_Access'Storage_pool use P ;

  procedure Info is new GNAT.Debug_Pools.Print_Info
                                ( Ada.Text_IO.Put_Line ) ;

  Ptr : aliased T_Access;

  I : Integer := -5 ;  -- Use for algorithm without memory leaks
  J : Positive ;
  K : Integer ;
  

begin

  --
  -- Algorithm without memory leaks!
  --
  -- In this version the code will generate a Constraint_Error
  -- before any routine needs any memory. Which means no Memory 
  -- Leak!
  --
  Ada.Text_IO.Put_Line ( "New Algorithm" ) ;
  Info ( P ) ;

  begin 
    J := Positive ( I ) ; 
    K := Integer ( J ) ;
    Ptr := new T ( K ) ;

    Ada.Integer_Text_IO.Put ( Ptr.all.C ) ;
    Ada.Text_IO.New_Line ;
  exception
    when Constraint_Error =>
      -- is memory leaked or deallocated?
      Ada.Text_IO.Put_Line ( "Constraint_Error" ) ;
      Info ( P ) ;
      null;
    when E : others => 
      Ada.Text_IO.Put_Line ( "Raised " & Exception_Name ( E ) ) ;
  end ;

  --
  -- Algorithm with memory leaks!
  --
  Ada.Text_IO.Put_Line ( "Old Algorithm" ) ;
  Info ( P ) ;

  Ptr := new T (-5);  

  Ada.Integer_Text_IO.Put ( Ptr.all.C ) ;
  Ada.Text_IO.New_Line ;
  Info ( P ) ;
exception
  when Constraint_Error =>
    -- is memory leaked or deallocated?
    Ada.Text_IO.Put_Line ( "Constraint_Error" ) ;
    Info ( P ) ;
    null;
  when E : others => 
    Ada.Text_IO.Put_Line ( "Raised " & Exception_Name ( E ) ) ;
end PZ;


In <1189323618.588340.87180@o80g2000hse.googlegroups.com>,  Maciej Sobczak <see.my.homepage@gmail.com> writes:
>What happens when during the initialization of the newly allocated
>object an exception is raised?
>
>I cannot find anything in the AARM that covers this case. What I want
>to find exactly is the *guarantee* that the allocated memory is
>automatically reclaimed.
>Any relevant paragraph numbers are highly welcome.
>
>--
>Maciej Sobczak
>http://www.msobczak.com/
>




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 19:07               ` Maciej Sobczak
  2007-09-11 22:56                 ` Georg Bauhaus
@ 2007-09-12  9:32                 ` Dmitry A. Kazakov
  2007-09-12 12:42                   ` Maciej Sobczak
  1 sibling, 1 reply; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-12  9:32 UTC (permalink / raw)


On Tue, 11 Sep 2007 12:07:06 -0700, Maciej Sobczak wrote:

> On 11 Wrz, 14:27, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> This error is likely unrecoverable, so you have to reconsider your design
>> which allowed such errors.
> 
> I disagree. The error might be unrecoverable (like broken network
> cable), but might as well be worth retrying with modified parameters
> (like wrong credentials were provided by the user).
> Even in unrecoverable case I might want to gracefully reduce the
> functionality of the system. Sorry, there will be no music today, but
> please enjoy the party anyway - this sort of thing.

Sure, but your design does not allow this. And establishing connection upon
construction is a bad idea anyway.

>> BTW, formally everything is exactly as you wished! Observe, that
>>
>>    new T(-5)
>>
>> creates an object of the type T_Access. This object does not come to
>> existence and the compiler carefully eliminates any traces of this object.
>> Everything is fine!
> 
> Except of the memory leak and the already created other components.

Which is not T_Access's business.

>> What you actually want, but didn't say it, is that T_Access would take care
>> of the things it points to, so its constructor (new) would.
> 
> No. T_Access is not (yet) involved. This has to be handled entirely by
> the allocator, because the whole problem happens even before T_Access
> is assigned to my access variable.

"new" is a method of T_Access, it is not of T. That's the whole point. You
want some intimate relations between T_Access and T. But there is no
unified way to define them. The language offers you only raw pointers. you
have to add some meat to these pointers. The gears Ada has for this job are
quite rudimentary, namely ad-hoc polymorphism (overloaded subprograms). Not
much. If T_Access had a user-defined constructor, you could handle
deallocation of target there upon exception propagation. But it does not.

>>> This is what allows me to keep abstractions and invariants: either I
>>> have the complete object with its guaranteed invariants, or there is
>>> nothing. Anything in between is mess.
>>
>> This is violated upon aggregation of initialized components with side
>> effects. I don't argue that this is good, I only state that this is the
>> current language design and that it would be quite challenging to alter.
> 
> I understand that it cannot be changed. At least not shortly after the
> last standardization iteration. :-)
> 
> But... did I mention that C++ handles this issue correctly? ;-)
> And no, it does not have any super-capable access types. A little bit
> smarter allocator is enough.

Really?

class Foo
{
   Baz * A;
   Bar * B;

   Foo () : A (new Baz), B (new Bar) { ... throw ... }

If initialization of B fails, A will not be freed. After execution of
throw, neither A nor B will be freed. C++ does not handle it correctly, it
just does it a bit less incorrect. (:-))

Ada lacks a consistent unified construction model (one for *all* types).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12  0:34       ` Jeffrey R. Carter
@ 2007-09-12 12:13         ` Maciej Sobczak
  2007-09-12 16:34           ` Jeffrey R. Carter
  0 siblings, 1 reply; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-12 12:13 UTC (permalink / raw)


On 12 Wrz, 02:34, "Jeffrey R. Carter"
<spam.jrcarter....@acm.nospam.org> wrote:

> It looks legal to me. I've added a little test to see what's happening
> with P:
[...]

> and get output:
>
> P = null => FALSE
>   123
>
> I suppose P could be dangling, with the memory it points to not yet
> reused, but I suspect that is not the case.

You did not check whether the deallocation was actually performed as a
result of the exception. If not, P points to a valid (although not
fully initialized) object. There is also no memory leak, since you
have references to all allocated objects.

You should create your own pool and trace the calls to Allocate/
Deallocate to conclude anything useful from such a test.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 21:56     ` Adam Beneschan
  2007-09-12  0:34       ` Jeffrey R. Carter
@ 2007-09-12 12:22       ` Maciej Sobczak
  2007-09-12 14:11         ` Markus E L
  2007-09-12 16:08         ` Adam Beneschan
  1 sibling, 2 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-12 12:22 UTC (permalink / raw)


On 11 Wrz, 23:56, Adam Beneschan <a...@irvine.com> wrote:

> OK, I think I have one.  GNAT compiles and runs it, although I haven't
> checked the language rules carefully to make sure it's legal.

Without checking the language rules carefully, I think this is a legal
program demonstrating artificially broken design.

Consider that there is no exception and instead you call
Unchecked_Deallocation after successfully creating the object.
The P pointer will be dangling.

So what is your example proving? That we can make dangling pointers in
Ada? This is already known.

Show me an example that is not artificially broken and that breaks
exactly because of the weaknesses of the idea that was discussed, not
because of the weaknesses that are in the rest of the example.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11  9:19           ` Maciej Sobczak
  2007-09-11 12:27             ` Dmitry A. Kazakov
@ 2007-09-12 12:29             ` Stephen Leake
  2007-09-12 12:46               ` Maciej Sobczak
  2007-09-12 14:14               ` Markus E L
  1 sibling, 2 replies; 55+ messages in thread
From: Stephen Leake @ 2007-09-12 12:29 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> On 11 Wrz, 11:16, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>
>> >>> P.S. Exceptions in constructors is a bad idea.
>>
>> > No, it's a very good idea. Otherwise you have to deal with half-baked
>> > objects, which is Even Bigger Mess (tm).
>>
>> This is what you get when the exception is propagated out of a constructor.
>
> In this case I want the constructor to be rolled back.
> Without exceptions (and rollback) the only option for handling errors
> in initialization of (sub)components is to leave them half-baked.

The point is that the constructor itself must do the roll-back, and
leave the object in a consistent state.

The rule should be:

    Constructors should not propagate exceptions up; they must handle
    all exceptions internally.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-11 22:56                 ` Georg Bauhaus
@ 2007-09-12 12:36                   ` Maciej Sobczak
  2007-09-12 22:19                     ` Randy Brukardt
  0 siblings, 1 reply; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-12 12:36 UTC (permalink / raw)


On 12 Wrz, 00:56, Georg Bauhaus <rm.tsoh+bauh...@maps.futureapps.de>
wrote:

> > But... did I mention that C++ handles this issue correctly? ;-)
> > And no, it does not have any super-capable access types. A little bit
> > smarter allocator is enough.
>
> C++ doesn't seem to handle deallocation etc. of sibling components
> either, so I'm not sure I understand.

It does. In case of exception the already constructed components are
rolled back. This works for components of array as well.

> Should the following be excluded from consideration? (The program
> quickly claims all available memory, as I would have expected; any
> pointers to what should I read to learn how this can be simply
> prevented in C++?)
>
> class T {
>    int c;
>    int *x;
> public:
>    T(int init) {
>       x = new int[1024];
>       if (init < 1) { throw "Constraint_Error"; }

Yes, this is very bad coding. We call it "C with classes" to clearly
distinguish it from C++.

Try this:

class T
{
   int c;
   vector<int> x;
public:
   T(int init)
   {
      x.resize(1024);
      if (init < 1) { throw "Constraint_Error"; }
   }

   // note: no destructor needed
};

Alternatively:

class T
{
   int c;
   scoped_array<int> x;
public:
   T(int init)
   {
      x = new int[1024];
      if (...
...

And so on.

C++ will roll-back all already created components by calling their
destructors. In your initial ("C with classes") example, there were
two components:

int c;
int *x;

Both will be properly rolled back, which here means do nothing - these
are fundamental types.

Use smarter types to get smarter rollback.
Use C++ instead of "C with classes" and the difference will be
significant.

Note that with smarter types the code is actually shorter (no explicit
destructor needed). Less coding, less bugs, ... ;-)

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12  9:32                 ` Dmitry A. Kazakov
@ 2007-09-12 12:42                   ` Maciej Sobczak
  2007-09-12 15:25                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-12 12:42 UTC (permalink / raw)


On 12 Wrz, 11:32, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> > Even in unrecoverable case I might want to gracefully reduce the
> > functionality of the system. Sorry, there will be no music today, but
> > please enjoy the party anyway - this sort of thing.
>
> Sure, but your design does not allow this.

Because it does not focus on this. It focuses on the problem, not on
what I could do if there was no problem.

> And establishing connection upon
> construction is a bad idea anyway.

Why?

> class Foo
> {
>    Baz * A;
>    Bar * B;

The biggest problem of C++ is not that it's crap, but that most people
were not exposed to correct idioms.

Try this:

   scoped_ptr<Baz> A;
   scoped_ptr<Bar> B;

There are other smart pointers, depending on the need.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:29             ` Stephen Leake
@ 2007-09-12 12:46               ` Maciej Sobczak
  2007-09-12 20:53                 ` Simon Wright
                                   ` (2 more replies)
  2007-09-12 14:14               ` Markus E L
  1 sibling, 3 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-12 12:46 UTC (permalink / raw)


On 12 Wrz, 14:29, Stephen Leake <stephen_le...@stephe-leake.org>
wrote:

> The rule should be:
>
>     Constructors should not propagate exceptions up; they must handle
>     all exceptions internally.

No.
What should the constructor do *after* handling the exception?
Leave the object half-baked?
Do you want to introduce additional states to the object design just
to handle the "oops I'm not initialized" case?

The only reasonable solution is probably to use custom factories
instead of built-in allocators.

But... can we prohibit the user from using the allocator for the given
type?

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:22       ` Maciej Sobczak
@ 2007-09-12 14:11         ` Markus E L
  2007-09-12 16:08         ` Adam Beneschan
  1 sibling, 0 replies; 55+ messages in thread
From: Markus E L @ 2007-09-12 14:11 UTC (permalink / raw)



Maciej Sobczak wrote:

> On 11 Wrz, 23:56, Adam Beneschan <a...@irvine.com> wrote:
>
>> OK, I think I have one.  GNAT compiles and runs it, although I haven't
>> checked the language rules carefully to make sure it's legal.
>
> Without checking the language rules carefully, I think this is a legal
> program demonstrating artificially broken design.

Yes, but: I see Unchecked_Access here, so I'm not surprised that some
guarantees are off. On the other side, I'd expect that failure during
initialization leads to dellocation. That would be sane, instead of
slowly leaking memory in a long running system. My impression is that
w/o using Unchecked_Access it will not be possible to produce dangling
references then.

(I haven't thought deeply about all this).

Regards-- Markus




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:29             ` Stephen Leake
  2007-09-12 12:46               ` Maciej Sobczak
@ 2007-09-12 14:14               ` Markus E L
  1 sibling, 0 replies; 55+ messages in thread
From: Markus E L @ 2007-09-12 14:14 UTC (permalink / raw)



Stephen Leake wrote:

> Maciej Sobczak <see.my.homepage@gmail.com> writes:
>
>> On 11 Wrz, 11:16, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>> wrote:
>>
>>> >>> P.S. Exceptions in constructors is a bad idea.
>>>
>>> > No, it's a very good idea. Otherwise you have to deal with half-baked
>>> > objects, which is Even Bigger Mess (tm).
>>>
>>> This is what you get when the exception is propagated out of a constructor.
>>
>> In this case I want the constructor to be rolled back.
>> Without exceptions (and rollback) the only option for handling errors
>> in initialization of (sub)components is to leave them half-baked.
>
> The point is that the constructor itself must do the roll-back, and
> leave the object in a consistent state.
>
> The rule should be:
>
>     Constructors should not propagate exceptions up; they must handle
>     all exceptions internally.

Forgive me that I contradict. The power of exceptions in a properly
designed language is, that it allows to handle problems during complex
object constructions, like

    T = new (something(new something_else ...)

and recover fully. Else we're back to testing failure after every step
again and manuall, as it was/is in C. Maybe I misunderstood the
problem altogether, though.

Regards --- Markus





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:42                   ` Maciej Sobczak
@ 2007-09-12 15:25                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-12 15:25 UTC (permalink / raw)


On Wed, 12 Sep 2007 05:42:50 -0700, Maciej Sobczak wrote:

> On 12 Wrz, 11:32, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> And establishing connection upon
>> construction is a bad idea anyway.
> 
> Why?

Because it takes time and it can be lost.

>> class Foo
>> {
>>    Baz * A;
>>    Bar * B;
> 
> The biggest problem of C++ is not that it's crap, but that most people
> were not exposed to correct idioms.
> 
> Try this:
> 
>    scoped_ptr<Baz> A;
>    scoped_ptr<Bar> B;
> 
> There are other smart pointers, depending on the need.

Huh, that is exactly my point. Don't use plain pointers. A factory used
instead of new T could do the work better.

As I said, composition of constructors is a right thing. It is good that
C++ does this (though not always incorrectly). It is bad that Ada does not.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:22       ` Maciej Sobczak
  2007-09-12 14:11         ` Markus E L
@ 2007-09-12 16:08         ` Adam Beneschan
  2007-09-12 20:35           ` Dmitry A. Kazakov
  1 sibling, 1 reply; 55+ messages in thread
From: Adam Beneschan @ 2007-09-12 16:08 UTC (permalink / raw)


On Sep 12, 5:22 am, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> On 11 Wrz, 23:56, Adam Beneschan <a...@irvine.com> wrote:
>
> > OK, I think I have one.  GNAT compiles and runs it, although I haven't
> > checked the language rules carefully to make sure it's legal.
>
> Without checking the language rules carefully, I think this is a legal
> program demonstrating artificially broken design.
>
> Consider that there is no exception and instead you call
> Unchecked_Deallocation after successfully creating the object.
> The P pointer will be dangling.
>
> So what is your example proving? That we can make dangling pointers in
> Ada? This is already known.

You can create dangling pointers and do all sorts of other bad stuff
by using "Unchecked" features like Unchecked_Deallocation, and other
things like 'Address clauses.  These are documented in the manual, and
it's pointed out that the user needs to know what they're doing or
else the result could be erroneous.  But the language shouldn't be
adding dangerous stuff like that automatically.
Unchecked_Deallocation is called "Unchecked" for a very good reason,
to remind those who use the routine that it could lead to trouble.
But the language can't start doing such unchecked stuff itself
automatically.

Now, I'm aware that I used an Unchecked thing ('Unchecked_Access) in
my example.  So far, I haven't been able to create an example that
doesn't.  But I'd want a *proof* that it's impossible for the
automatic deallocation you're asking for could not create a dangling
pointer in the absence of Unchecked or other dangerous features, and
I'm not yet convinced.  (And your earlier statement that  "the object
simply does not exist" falls several miles short of a proof, and my
example proves that that is wrong anyway, because the object does
exist temporarily.)

But you seem to be suggesting that the language should just do the
"right thing" anyway (i.e. deallocate the object), and if a certain
combination of legal features leads to a disaster like a dangling
pointer, you throw up your hands and blame it on a broken design.
That's the C++ way, not the Ada way.  In Ada, safety is important.  We
try to make sure programs can't cause this sort of problem unless the
user deliberately does something that is known to be dangerous.

By the way, although I think having the language deallocate the object
automatically is a bad idea, I do sympathize with the problem that
it's impossible to get a hold of the access value that was already
allocated so that you can do an Unchecked_Deallocation yourself.  None
of the workarounds seem all that good.  Unfortunately, I can't think
of a good way to add this to the language.

                        -- Adam





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:13         ` Maciej Sobczak
@ 2007-09-12 16:34           ` Jeffrey R. Carter
  2007-09-12 23:50             ` Jeffrey R. Carter
  0 siblings, 1 reply; 55+ messages in thread
From: Jeffrey R. Carter @ 2007-09-12 16:34 UTC (permalink / raw)


Maciej Sobczak wrote:
> 
> You should create your own pool and trace the calls to Allocate/
> Deallocate to conclude anything useful from such a test.

I leave that as an exercise for the reader.

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 16:08         ` Adam Beneschan
@ 2007-09-12 20:35           ` Dmitry A. Kazakov
  2007-09-12 21:01             ` Adam Beneschan
  2007-09-12 22:45             ` Randy Brukardt
  0 siblings, 2 replies; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-12 20:35 UTC (permalink / raw)


On Wed, 12 Sep 2007 09:08:18 -0700, Adam Beneschan wrote:

> By the way, although I think having the language deallocate the object
> automatically is a bad idea,

How to reconcile this with:

1. objects allocated on the stack

2. all sorts of temporal objects the compiler is allowed to create (and
thus allocate somehow, somewhere)

3. a permission given to collect garbage?

Anyway, presuming that the constructor shall clean its mess before
propagating any exceptions, there is no any object here to "deallocate" (I
would say "destroy").

> I do sympathize with the problem that
> it's impossible to get a hold of the access value that was already
> allocated so that you can do an Unchecked_Deallocation yourself.  None
> of the workarounds seem all that good.  Unfortunately, I can't think
> of a good way to add this to the language.

Unchecked_Deallocation may not be called on a pointer to non-constructed
objects. Semantically it is not a pointer at all. It is a raw address on
which Deallocate has to be called. This is indeed a problem. If Ptr is
invalid, then Ptr.all'Address is erroneous.

A related issue, why on earth "new" is allowed to propagate anything but
Storage_Error or else Program_Error?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:46               ` Maciej Sobczak
@ 2007-09-12 20:53                 ` Simon Wright
  2007-09-12 22:32                   ` Randy Brukardt
  2007-09-12 22:25                 ` Randy Brukardt
  2007-09-13 11:51                 ` Stephen Leake
  2 siblings, 1 reply; 55+ messages in thread
From: Simon Wright @ 2007-09-12 20:53 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> What should the constructor do *after* handling the exception?
> Leave the object half-baked?

I'm not sure exactly what Stephe meant by 'propagate'. It certainly
seems a bad idea to allow a Constraint_Error to propagate
unhandled. But what would be wrong with dealing with the problem and
then raising an appropriate exception from the constructor? (even
Constraint_Error if gnat makes sense).

--S



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 20:35           ` Dmitry A. Kazakov
@ 2007-09-12 21:01             ` Adam Beneschan
  2007-09-12 22:45             ` Randy Brukardt
  1 sibling, 0 replies; 55+ messages in thread
From: Adam Beneschan @ 2007-09-12 21:01 UTC (permalink / raw)


On Sep 12, 1:35 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Wed, 12 Sep 2007 09:08:18 -0700, Adam Beneschan wrote:
> > By the way, although I think having the language deallocate the object
> > automatically is a bad idea,
>
> How to reconcile this with:
>
> 1. objects allocated on the stack
>
> 2. all sorts of temporal objects the compiler is allowed to create (and
> thus allocate somehow, somewhere)
>
> 3. a permission given to collect garbage?

There's nothing to reconcile, because I didn't say that the language
should never deallocate *any* object automatically; I think you'd have
to take my sentence out of context to read it that way.  In the
particular case we're discussing on this thread, my objection is that
I'm not convinced a dangling pointer couldn't be created (by using
"normal" features of the language, not Unchecked features).  By
contrast, the language rules do prevent this in cases #1 and #2: in
case #1, by the accessibility rules; in case #2, I think it's because
only for limited types can you take the 'Access of the "current
instance", and the build-in-place rules ensure that anonymous objects
aren't created for limited types.  For #3, a working garbage collector
by definition won't deallocate anything that isn't pointed to.

                          -- Adam






^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:36                   ` Maciej Sobczak
@ 2007-09-12 22:19                     ` Randy Brukardt
  0 siblings, 0 replies; 55+ messages in thread
From: Randy Brukardt @ 2007-09-12 22:19 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message
news:1189600614.629447.86470@k79g2000hse.googlegroups.com...
> On 12 Wrz, 00:56, Georg Bauhaus <rm.tsoh+bauh...@maps.futureapps.de>
> wrote:
>
> > > But... did I mention that C++ handles this issue correctly? ;-)
> > > And no, it does not have any super-capable access types. A little bit
> > > smarter allocator is enough.
> >
> > C++ doesn't seem to handle deallocation etc. of sibling components
> > either, so I'm not sure I understand.
>
> It does. In case of exception the already constructed components are
> rolled back. This works for components of array as well.

Ada does of course finalize any components that have already been
constructed. It doesn't just drop them on the floor!! The problem (if you
can call it that) with Ada is that is clearly defines when that will happen.
You want it to happen *earlier* than that definition.

One could argue that that definition is wrong, but it is what it is.

For what it's worth, the definition you seem to want would be extremely
expensive to implement in Janus/Ada: every allocated component would need a
dedicated (compiler generated) exception handler in order to be able free
the associated memory immediately. The effect would be to make allocators 10
times bigger and possibly 10 times slower. (It surely would be that much for
our [obsolete] MS-DOS compilers, which used a heap of our own design; I'm
not sure how expensive the Windows heap allocations are so it might be
somewhat less.) Programs that do a lot of allocation could have a pretty
significant performance impact (and that would include the containers
libraries).

                                        Randy.





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:46               ` Maciej Sobczak
  2007-09-12 20:53                 ` Simon Wright
@ 2007-09-12 22:25                 ` Randy Brukardt
  2007-09-13 11:51                 ` Stephen Leake
  2 siblings, 0 replies; 55+ messages in thread
From: Randy Brukardt @ 2007-09-12 22:25 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message
news:1189601170.835400.72630@w3g2000hsg.googlegroups.com...
> On 12 Wrz, 14:29, Stephen Leake <stephen_le...@stephe-leake.org>
> wrote:
>
> > The rule should be:
> >
> >     Constructors should not propagate exceptions up; they must handle
> >     all exceptions internally.
>
> No.
> What should the constructor do *after* handling the exception?
> Leave the object half-baked?

No, unbaked.

> Do you want to introduce additional states to the object design just
> to handle the "oops I'm not initialized" case?

No, because you must have those states anyway. Ada allows an object to be
finalized multiple times (either by an explicit call to Finalize, or in some
obscure cases involving aborts), so you have to have an invalid (not between
initialization and finalization) state in any Ada controlled object.
(Blindly doubly finalizing an object is likely to be a serious bug, because
of calling Unchecked_Deallocation twice on the same object or similar
gaffes.) Any controlled type that doesn't have an "I'm not valid" state is
wrong, period.

Once you have such a state, having an uninitialized object is not a
disaster.

                               Randy.





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 20:53                 ` Simon Wright
@ 2007-09-12 22:32                   ` Randy Brukardt
  2007-09-12 23:43                     ` Simon Wright
                                       ` (2 more replies)
  0 siblings, 3 replies; 55+ messages in thread
From: Randy Brukardt @ 2007-09-12 22:32 UTC (permalink / raw)


"Simon Wright" <simon.j.wright@mac.com> wrote in message
news:m2ir6fobaz.fsf@mac.com...
> Maciej Sobczak <see.my.homepage@gmail.com> writes:
>
> > What should the constructor do *after* handling the exception?
> > Leave the object half-baked?
>
> I'm not sure exactly what Stephe meant by 'propagate'. It certainly
> seems a bad idea to allow a Constraint_Error to propagate
> unhandled. But what would be wrong with dealing with the problem and
> then raising an appropriate exception from the constructor? (even
> Constraint_Error if gnat makes sense).

Because Ada *requires* storage leakage in such cases (although some
compilers ignore the language definition and finalize anyway). An allocated
object cannot be finalized until it's *type* is finalized or until an
Unchecked_Deallocation is called -- and an Unchecked_Deallocation is not
going to be called if a constructor propagates an exception. So the
(inaccessible) object is supposed to hang around for a long, long time.

The "proper" way to handle this is to ensure that default initialize of an
object never propagates an exception, and then wrap the allocator properly:

    type Access_T is access all T;
    procedure Free is new Unchecked_Deallocation (T, Access_T);
    function Alloc_Object (...) return Access_T is
       A_T : Access_T := new T; -- Default initialized.
    begin
       A_T.all := <constructor>;
       return A_T;
    exception
        when others => Free(A_T); return null;
    end Alloc_Object;

But I'm not going to argue that this is an ugly and complex way of handling
this.

                    Randy.





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 20:35           ` Dmitry A. Kazakov
  2007-09-12 21:01             ` Adam Beneschan
@ 2007-09-12 22:45             ` Randy Brukardt
  2007-09-13  7:48               ` Dmitry A. Kazakov
  1 sibling, 1 reply; 55+ messages in thread
From: Randy Brukardt @ 2007-09-12 22:45 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:1bi8swgas8pjl$.1tr7pfyemom8q.dlg@40tude.net...
> On Wed, 12 Sep 2007 09:08:18 -0700, Adam Beneschan wrote:
>
> > By the way, although I think having the language deallocate the object
> > automatically is a bad idea,
>
> How to reconcile this with:
>
> 1. objects allocated on the stack
>
> 2. all sorts of temporal objects the compiler is allowed to create (and
> thus allocate somehow, somewhere)
>
> 3. a permission given to collect garbage?

That's the *real* problem: Ada has no such permission when it comes to
objects with non-trivial finalization. It is defined precisely where they
are going to be finalized, and there is no permission to do it early without
an explicit call (which doesn't exist).

As it stands, a compiler that does the right thing (in the sense of avoiding
a memory leak when it is certain that no reference to the object remain) is
actually wrong vis-a-vis the language definition.

> Anyway, presuming that the constructor shall clean its mess before
> propagating any exceptions, there is no any object here to "deallocate" (I
> would say "destroy").

Surely the top-level object's memory was allocated, and there is no place in
the language that would ever require Deallocate to be called. Moreover, even
a friendly compiler could not do that without violating the language
definition.

> > I do sympathize with the problem that
> > it's impossible to get a hold of the access value that was already
> > allocated so that you can do an Unchecked_Deallocation yourself.  None
> > of the workarounds seem all that good.  Unfortunately, I can't think
> > of a good way to add this to the language.
>
> Unchecked_Deallocation may not be called on a pointer to non-constructed
> objects. Semantically it is not a pointer at all. It is a raw address on
> which Deallocate has to be called. This is indeed a problem. If Ptr is
> invalid, then Ptr.all'Address is erroneous.
>
> A related issue, why on earth "new" is allowed to propagate anything but
> Storage_Error or else Program_Error?

"new" doesn't propagate anything other than Storage_Error or Program_Error.
The initialization expression, OTOH, can propagate anything it wants. Those
are separate things from a language perspective; the problem is that you
can't *write* them separately.

                                  Randy.





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 22:32                   ` Randy Brukardt
@ 2007-09-12 23:43                     ` Simon Wright
  2007-09-13  3:42                       ` Randy Brukardt
  2007-09-13  3:36                     ` Randy Brukardt
  2007-09-13  9:43                     ` Maciej Sobczak
  2 siblings, 1 reply; 55+ messages in thread
From: Simon Wright @ 2007-09-12 23:43 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Simon Wright" <simon.j.wright@mac.com> wrote in message
> news:m2ir6fobaz.fsf@mac.com...
>> Maciej Sobczak <see.my.homepage@gmail.com> writes:
>>
>> > What should the constructor do *after* handling the exception?
>> > Leave the object half-baked?
>>
>> I'm not sure exactly what Stephe meant by 'propagate'. It certainly
>> seems a bad idea to allow a Constraint_Error to propagate
>> unhandled. But what would be wrong with dealing with the problem and
>> then raising an appropriate exception from the constructor? (even
>> Constraint_Error if gnat makes sense).
                       that
>
> Because Ada *requires* storage leakage in such cases (although some
> compilers ignore the language definition and finalize anyway). An
> allocated object cannot be finalized until it's *type* is finalized
> or until an Unchecked_Deallocation is called -- and an
> Unchecked_Deallocation is not going to be called if a constructor
> propagates an exception. So the (inaccessible) object is supposed to
> hang around for a long, long time.
>
> The "proper" way to handle this is to ensure that default initialize
> of an object never propagates an exception, and then wrap the
> allocator properly:
>
>     type Access_T is access all T;
>     procedure Free is new Unchecked_Deallocation (T, Access_T);
>     function Alloc_Object (...) return Access_T is
>        A_T : Access_T := new T; -- Default initialized.
>     begin
>        A_T.all := <constructor>;
>        return A_T;
>     exception
>         when others => Free(A_T); return null;
>     end Alloc_Object;

I guess I had misunderstood what's meant by 'constructor', becasue
this is just what I had in mind ... and there are far worse things to
leak than memory, such as locks, file handles, data structure
integrity etc, and those we can handle even in a constructor (ie
function returning a value of the type rather than a pointer to a new
value of the type).



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 16:34           ` Jeffrey R. Carter
@ 2007-09-12 23:50             ` Jeffrey R. Carter
  0 siblings, 0 replies; 55+ messages in thread
From: Jeffrey R. Carter @ 2007-09-12 23:50 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> Maciej Sobczak wrote:
>>
>> You should create your own pool and trace the calls to Allocate/
>> Deallocate to conclude anything useful from such a test.
> 
> I leave that as an exercise for the reader.

FWIW, I've tried this exercise. As expected, Deallocate is not called.

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 22:32                   ` Randy Brukardt
  2007-09-12 23:43                     ` Simon Wright
@ 2007-09-13  3:36                     ` Randy Brukardt
  2007-09-13  9:43                     ` Maciej Sobczak
  2 siblings, 0 replies; 55+ messages in thread
From: Randy Brukardt @ 2007-09-13  3:36 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> wrote in message
news:fc9p94$rt6$1@jacob-sparre.dk...
...
> Because Ada *requires* storage leakage in such cases (although some
> compilers ignore the language definition and finalize anyway). An
allocated
> object cannot be finalized until it's *type* is finalized or until an
> Unchecked_Deallocation is called -- and an Unchecked_Deallocation is not
> going to be called if a constructor propagates an exception. So the
> (inaccessible) object is supposed to hang around for a long, long time.

For what it's worth, the rule in the RM is 7.6.1(10), which says:

"Immediately before an instance of Unchecked_Deallocation reclaims the
storage of an object, the object is finalized. If an instance of
Unchecked_Deallocation is never applied to an object created by an
allocator, the object will still exist when the corresponding master
completes, and it will be finalized then."

                      Randy.





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 23:43                     ` Simon Wright
@ 2007-09-13  3:42                       ` Randy Brukardt
  0 siblings, 0 replies; 55+ messages in thread
From: Randy Brukardt @ 2007-09-13  3:42 UTC (permalink / raw)


"Simon Wright" <simon.j.wright@mac.com> wrote in message
news:m2abrro3f0.fsf@mac.com...
> "Randy Brukardt" <randy@rrsoftware.com> writes:
...
> > The "proper" way to handle this is to ensure that default initialize
> > of an object never propagates an exception, and then wrap the
> > allocator properly:
> >
> >     type Access_T is access all T;
> >     procedure Free is new Unchecked_Deallocation (T, Access_T);
> >     function Alloc_Object (...) return Access_T is
> >        A_T : Access_T := new T; -- Default initialized.
> >     begin
> >        A_T.all := <constructor>;
> >        return A_T;
> >     exception
> >         when others => Free(A_T); return null;
> >     end Alloc_Object;
>
> I guess I had misunderstood what's meant by 'constructor', becasue
> this is just what I had in mind ... and there are far worse things to
> leak than memory, such as locks, file handles, data structure
> integrity etc, and those we can handle even in a constructor (ie
> function returning a value of the type rather than a pointer to a new
> value of the type).

The problem with this sort of construction (besides that it is clunky) is
that is doesn't work for limited types without breaking abstraction. OTOH,
the leak in this case doesn't bother me too much, because constructor
failure ought to be rare and it is also rare to be creating a lot of
objects -- so it usually doesn't matter. Moreover, safety critical
applications aren't going to be using allocators in the first place, and
very long-running applications are likely to have problems with memory
fragmentation even if they don't leak any memory -- unless they have a lot
more memory available than they're going to need. Still, the leak is
uncomfortable - it doesn't match Ada's goals.

                 Randy.





^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 22:45             ` Randy Brukardt
@ 2007-09-13  7:48               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 55+ messages in thread
From: Dmitry A. Kazakov @ 2007-09-13  7:48 UTC (permalink / raw)


On Wed, 12 Sep 2007 17:45:07 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:1bi8swgas8pjl$.1tr7pfyemom8q.dlg@40tude.net...

> As it stands, a compiler that does the right thing (in the sense of avoiding
> a memory leak when it is certain that no reference to the object remain) is
> actually wrong vis-a-vis the language definition.

This need to be fixed.

>> Unchecked_Deallocation may not be called on a pointer to non-constructed
>> objects. Semantically it is not a pointer at all. It is a raw address on
>> which Deallocate has to be called. This is indeed a problem. If Ptr is
>> invalid, then Ptr.all'Address is erroneous.
>>
>> A related issue, why on earth "new" is allowed to propagate anything but
>> Storage_Error or else Program_Error?
> 
> "new" doesn't propagate anything other than Storage_Error or Program_Error.
> The initialization expression, OTOH, can propagate anything it wants. Those
> are separate things from a language perspective; the problem is that you
> can't *write* them separately.

Because there is no constructors. One can reject Maciej's idea of rolling
everything back, but then the language shall be consistent with
un-/partially constructed objects, hence constructors made visible, storage
pools visible, etc, in order to manually roll a failed initialization back
and then to deallocate. Otherwise, it shall not allow such objects. The
second choice *implies* that any exceptions propagating through "new" were
illegal, hence converted to Program_Error. The current status is obviously
unsatisfactory.

As for your concern about efficiency of construction with exceptions. I
think that contracted exceptions could fix that nicely. With them Maciej's
example:

   type T (Init : Integer) is record
      C : Positive := Positive (Init);
   end record;

would become illegal because the default contract of T's constructor will
be exception-free. The compiler will reject Positive applied to Init for
the component C as potentially raising an unlisted exception. No any
roll-back code need to be generated. In rare cases when Constraint_Error
exception were indeed the programmer's intention, he could add it to the
contract and so the compiler would say - aha, this is what you want, then I
will generate roll-back stuff for this.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 22:32                   ` Randy Brukardt
  2007-09-12 23:43                     ` Simon Wright
  2007-09-13  3:36                     ` Randy Brukardt
@ 2007-09-13  9:43                     ` Maciej Sobczak
  2 siblings, 0 replies; 55+ messages in thread
From: Maciej Sobczak @ 2007-09-13  9:43 UTC (permalink / raw)


On 13 Wrz, 00:32, "Randy Brukardt" <ra...@rrsoftware.com> wrote:

>     type Access_T is access all T;
>     procedure Free is new Unchecked_Deallocation (T, Access_T);
>     function Alloc_Object (...) return Access_T is
>        A_T : Access_T := new T; -- Default initialized.
>     begin
>        A_T.all := <constructor>;
>        return A_T;
>     exception
>         when others => Free(A_T); return null;
>     end Alloc_Object;

Yes, this is a very reasonable approach. I would even propagate (or
translate) the exception out instead of returning null - this can make
it more plausible to work with at the call site.

--
Maciej Sobczak
http://www.msobczak.com/




^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: Allocators and exceptions
  2007-09-12 12:46               ` Maciej Sobczak
  2007-09-12 20:53                 ` Simon Wright
  2007-09-12 22:25                 ` Randy Brukardt
@ 2007-09-13 11:51                 ` Stephen Leake
  2 siblings, 0 replies; 55+ messages in thread
From: Stephen Leake @ 2007-09-13 11:51 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> On 12 Wrz, 14:29, Stephen Leake <stephen_le...@stephe-leake.org>
> wrote:
>
>> The rule should be:
>>
>>     Constructors should not propagate exceptions up; they must handle
>>     all exceptions internally.
>
> No.
> What should the constructor do *after* handling the exception?
> Leave the object half-baked?
> Do you want to introduce additional states to the object design just
> to handle the "oops I'm not initialized" case?
>
> The only reasonable solution is probably to use custom factories
> instead of built-in allocators.
>
> But... can we prohibit the user from using the allocator for the given
> type?

Hmm. You seem to be equating "allocator" with "constructor"; I was
not.

I thought you meant "custom factory" when you said "constructor".

Hmm. Maybe you mean only Finalization.Initialize by "constructor";
that is called by "new".

In any case, I'll modify my statement;

    Constructors (ie Initialize or user-built factory functions) must
    handle all exceptions internally. If in some situation the object
    cannot be properly constructed, any memory allocated should be
    deallocated, all other appropriate cleanups done, and then a final
    "Failed" exception should be raised to indicate the failure to the
    caller.

The point is that the caller of the constructor either gets a properly
initialized object, or a single well-defined exception indicating that
the object could not be created. In the latter case, all proper
cleanup is already done by the time the final exception is raised.

I think that is consistent with what you want to have happen.

If the constructor is designed to return an access value, an
alternative to raising the final exception is to return null, but an
exception is probably better.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2007-09-13 11:51 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-09-09  7:40 Allocators and exceptions Maciej Sobczak
2007-09-09 12:17 ` anon
2007-09-09 20:31   ` Maciej Sobczak
2007-09-09 22:43     ` Simon Wright
2007-09-10 12:10       ` Maciej Sobczak
2007-09-10 19:08         ` Simon Wright
2007-09-10  2:56     ` anon
2007-09-10 12:42     ` Dmitry A. Kazakov
2007-09-10 21:48       ` Maciej Sobczak
2007-09-11  9:16         ` Dmitry A. Kazakov
2007-09-11  9:19           ` Maciej Sobczak
2007-09-11 12:27             ` Dmitry A. Kazakov
2007-09-11 19:07               ` Maciej Sobczak
2007-09-11 22:56                 ` Georg Bauhaus
2007-09-12 12:36                   ` Maciej Sobczak
2007-09-12 22:19                     ` Randy Brukardt
2007-09-12  9:32                 ` Dmitry A. Kazakov
2007-09-12 12:42                   ` Maciej Sobczak
2007-09-12 15:25                     ` Dmitry A. Kazakov
2007-09-12 12:29             ` Stephen Leake
2007-09-12 12:46               ` Maciej Sobczak
2007-09-12 20:53                 ` Simon Wright
2007-09-12 22:32                   ` Randy Brukardt
2007-09-12 23:43                     ` Simon Wright
2007-09-13  3:42                       ` Randy Brukardt
2007-09-13  3:36                     ` Randy Brukardt
2007-09-13  9:43                     ` Maciej Sobczak
2007-09-12 22:25                 ` Randy Brukardt
2007-09-13 11:51                 ` Stephen Leake
2007-09-12 14:14               ` Markus E L
2007-09-10 10:37 ` Allocators and exceptions => Read Me First anon
2007-09-10 12:16   ` Maciej Sobczak
2007-09-10 22:10     ` Allocators and exceptions => Trying Again anon
2007-09-10 23:15       ` Markus E L
2007-09-10 15:44 ` Allocators and exceptions Adam Beneschan
2007-09-10 21:58   ` Maciej Sobczak
2007-09-10 22:07   ` Jeffrey R. Carter
2007-09-11  9:14   ` Dmitry A. Kazakov
2007-09-11  9:23     ` Maciej Sobczak
2007-09-11  2:36 ` Randy Brukardt
2007-09-11 15:33   ` Adam Beneschan
2007-09-11 19:21     ` Maciej Sobczak
2007-09-11 21:56     ` Adam Beneschan
2007-09-12  0:34       ` Jeffrey R. Carter
2007-09-12 12:13         ` Maciej Sobczak
2007-09-12 16:34           ` Jeffrey R. Carter
2007-09-12 23:50             ` Jeffrey R. Carter
2007-09-12 12:22       ` Maciej Sobczak
2007-09-12 14:11         ` Markus E L
2007-09-12 16:08         ` Adam Beneschan
2007-09-12 20:35           ` Dmitry A. Kazakov
2007-09-12 21:01             ` Adam Beneschan
2007-09-12 22:45             ` Randy Brukardt
2007-09-13  7:48               ` Dmitry A. Kazakov
2007-09-12  3:08 ` Allocators and exceptions -- Debugging says memory leak! anon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox