comp.lang.ada
 help / color / mirror / Atom feed
* Problems with Scope of aliased Objects
@ 2009-04-16 13:43 patrick.gunia
  2009-04-16 15:29 ` Adam Beneschan
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: patrick.gunia @ 2009-04-16 13:43 UTC (permalink / raw)


Hi all,
I`ve got a question concerning the scope of Ada-variables. I got the
following situation:
First Approach:
- I declare a local variable "A" of type "xy" within the declaration
part of a procedure
- the variable-members are set and finally put into an array
=> after leaving the procedure the variables are still accessable
through the Array which is defined on a higher scope-level

Second Approach:
Now I want to restructure my code using general Access-Types for the
declared variables.
- I declare a variable "refA" as an alias to my variable-type
"xy" (also in the declaration-part of the procedure)
- I do the same operations on "refA" I did before on "A"
- I declare an instance of a general access-type to my variable of
type "xy" (also in the declaration-part of the procedure)
- I pass the access-type-Instance into the Array
=> after leaving the function, I get errors during runtime

Third Approach:
My third approach works, but uses Heap-Memory for "A" thus I generate
the instances dynamically within my procedure and then pass the
general access-types into my array.

Now here´s my explanation for this:
When leaving the function in my second approach the pointers are still
avaiable, because they´re passed into the array, but the objects, the
pointer point to are not, because they´re out of scope and thus
destroyed. Is this rigth? Anf if so, what do I have to do, to get my
second approach running, and not losing my locally declared objects
after leaving the function.

The reason why I restructure using access-types is that I want to use
the array for keeping instances of different classes within a class
hierarchy and thus I have to declare it as an array for general access
types to my root-class.

Thank you for your help!



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 13:43 Problems with Scope of aliased Objects patrick.gunia
@ 2009-04-16 15:29 ` Adam Beneschan
  2009-04-16 15:59   ` patrick.gunia
  2009-04-16 15:47 ` Dmitry A. Kazakov
  2009-04-16 15:50 ` Ludovic Brenta
  2 siblings, 1 reply; 12+ messages in thread
From: Adam Beneschan @ 2009-04-16 15:29 UTC (permalink / raw)


On Apr 16, 6:43 am, "patrick.gu...@googlemail.com"
<patrick.gu...@googlemail.com> wrote:
> Hi all,
> I`ve got a question concerning the scope of Ada-variables. I got the
> following situation:
> First Approach:
> - I declare a local variable "A" of type "xy" within the declaration
> part of a procedure
> - the variable-members are set and finally put into an array
> => after leaving the procedure the variables are still accessable
> through the Array which is defined on a higher scope-level
>
> Second Approach:
> Now I want to restructure my code using general Access-Types for the
> declared variables.
> - I declare a variable "refA" as an alias to my variable-type
> "xy" (also in the declaration-part of the procedure)
> - I do the same operations on "refA" I did before on "A"
> - I declare an instance of a general access-type to my variable of
> type "xy" (also in the declaration-part of the procedure)
> - I pass the access-type-Instance into the Array
> => after leaving the function, I get errors during runtime
>
> Third Approach:
> My third approach works, but uses Heap-Memory for "A" thus I generate
> the instances dynamically within my procedure and then pass the
> general access-types into my array.
>
> Now here´s my explanation for this:
> When leaving the function in my second approach the pointers are still
> avaiable, because they´re passed into the array, but the objects, the
> pointer point to are not, because they´re out of scope and thus
> destroyed. Is this rigth?

Yes.

> Anf if so, what do I have to do, to get my
> second approach running, and not losing my locally declared objects
> after leaving the function.

This is impossible (unless I am completely misunderstanding what
you're trying to do).  When you leave a function, any locally declared
objects (objects declared in the declarative part of the function) are
lost, period.  It sounds like you may not be aware of how local
variables are implemented in a typical implementation.  But when a
function or procedure starts, it will allocate a certain amount of
memory space on the stack, which it uses for local variables.  When it
returns, the stack pointer is set back to what it was before, and the
stack space can then be reused for the local variables belonging to a
*different* function or procedure (as well as for other information
that the processor leaves on the stack).  That means that the memory
for the local variables you used for the first procedure will get
overwritten, and the accesses that you've set up to point to those
local variables become useless.  That's why your second approach got
errors; the Ada language has built-in checks to prevent you from doing
something like this.

Using heap memory (the third approach) is what you'll need to do.  If
you have some objection to using heap memory or some problem you think
it would cause, please let us know what the problem is, and we should
be able to help you figure out what Ada features exist to alleviate
the problem.

                               -- Adam




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

* Re: Problems with Scope of aliased Objects
  2009-04-16 13:43 Problems with Scope of aliased Objects patrick.gunia
  2009-04-16 15:29 ` Adam Beneschan
@ 2009-04-16 15:47 ` Dmitry A. Kazakov
  2009-04-16 19:12   ` sjw
  2009-04-16 15:50 ` Ludovic Brenta
  2 siblings, 1 reply; 12+ messages in thread
From: Dmitry A. Kazakov @ 2009-04-16 15:47 UTC (permalink / raw)


On Thu, 16 Apr 2009 06:43:22 -0700 (PDT), patrick.gunia@googlemail.com
wrote:

> I`ve got a question concerning the scope of Ada-variables. I got the
> following situation:
> First Approach:
> - I declare a local variable "A" of type "xy" within the declaration
> part of a procedure
> - the variable-members are set and finally put into an array
> => after leaving the procedure the variables are still accessable
> through the Array which is defined on a higher scope-level

This is wrong because it is not the variables declared in the procedure,
but copies of their values stored in the array elements.
 
> Second Approach:
> Now I want to restructure my code using general Access-Types for the
> declared variables.
> - I declare a variable "refA" as an alias to my variable-type
> "xy" (also in the declaration-part of the procedure)
> - I do the same operations on "refA" I did before on "A"
> - I declare an instance of a general access-type to my variable of
> type "xy" (also in the declaration-part of the procedure)
> - I pass the access-type-Instance into the Array
> => after leaving the function, I get errors during runtime

This makes no sense because of dangling pointers.

> Third Approach:
> My third approach works, but uses Heap-Memory for "A" thus I generate
> the instances dynamically within my procedure and then pass the
> general access-types into my array.

Create an array of pointers initialized by allocated objects.

> Now here�s my explanation for this:
> When leaving the function in my second approach the pointers are still
> avaiable, because they�re passed into the array, but the objects, the
> pointer point to are not, because they�re out of scope and thus
> destroyed. Is this rigth?

Yes, you have dangling pointers.

> Anf if so, what do I have to do, to get my
> second approach running, and not losing my locally declared objects
> after leaving the function.

You have to allocate the objects using 'new':

   type Object is abstract ...;
   type Object_Ptr is access Object'Class;
   procedure Free is
       new Ada.Unchecked_Deallocation (Object'Class, Object_Ptr);

   type Objects_Array is array (Positive range <>) of Object_Ptr;

   procedure Foo (Data : Objects_Array);

       -- Derived types
   type This_Object is new Object with ...;
   type That_Object is new Object with ...;

declare
   Data : Objects_Array := (new This_Object, new That_Object);
begin
   ...
   Foo (Data); -- Deal with the array
   ...
   for I in Data'Range loop
      Free (Data (I)); -- Do not forget to destroy objects
   end loop;
end;

Fourth solution could be to use a container of unconstrained objects or a
container of smart pointers if the objects are limited.

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



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 13:43 Problems with Scope of aliased Objects patrick.gunia
  2009-04-16 15:29 ` Adam Beneschan
  2009-04-16 15:47 ` Dmitry A. Kazakov
@ 2009-04-16 15:50 ` Ludovic Brenta
  2009-04-16 16:01   ` Adam Beneschan
  2 siblings, 1 reply; 12+ messages in thread
From: Ludovic Brenta @ 2009-04-16 15:50 UTC (permalink / raw)


Hi Patrick,

Why don't you pass the outer array as an "in out" parameter to your
subprogram and let the subprogram write directly into the array? Or,
alternatively, pass a single component of the array as an "in out"
parameter and let the subprogram change it in place? i.e.

declare
   Outer_Array : array (1 .. 10) of Integer;
   procedure P (Component : in out Integer);
begin
   for K in Outer_Array'Range loop
      P (Component => Outer_Array (K));
   end loop;
end;

--
Ludovic Brenta.



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 15:29 ` Adam Beneschan
@ 2009-04-16 15:59   ` patrick.gunia
  2009-04-16 16:26     ` Adam Beneschan
  0 siblings, 1 reply; 12+ messages in thread
From: patrick.gunia @ 2009-04-16 15:59 UTC (permalink / raw)


> This is impossible (unless I am completely misunderstanding what
> you're trying to do).  When you leave a function, any locally declared
> objects (objects declared in the declarative part of the function) are
> lost, period.  It sounds like you may not be aware of how local
> variables are implemented in a typical implementation.  But when a
> function or procedure starts, it will allocate a certain amount of
> memory space on the stack, which it uses for local variables.  When it
> returns, the stack pointer is set back to what it was before, and the
> stack space can then be reused for the local variables belonging to a
> *different* function or procedure (as well as for other information
> that the processor leaves on the stack).  That means that the memory
> for the local variables you used for the first procedure will get
> overwritten, and the accesses that you've set up to point to those
> local variables become useless.  That's why your second approach got
> errors; the Ada language has built-in checks to prevent you from doing
> something like this.
>
> Using heap memory (the third approach) is what you'll need to do.  If
> you have some objection to using heap memory or some problem you think
> it would cause, please let us know what the problem is, and we should
> be able to help you figure out what Ada features exist to alleviate
> the problem.
>
>                                -- Adam

Alright, this was my explanation. I forgot the fact, that the values
are copied into the array. The simple reason why I didn´t want to use
heap-memory is the performance-aspect. My third approach works using
"new" to allocate heap-memory dynamically. In this case, adding the
access-type into the array leads to a copy of the heap-memory-adress
where the object was created. This address is copied into the array
and thus still reachable. To cut a long story short, my second
approach simply won´t work because of dangling pointers which point to
memory which isn´t assigned any longer (at least not to the objects I
expect to be there). Do I have to be afraid of runtime-performance-
problems when using dynamic allocation in Ada?



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 15:50 ` Ludovic Brenta
@ 2009-04-16 16:01   ` Adam Beneschan
  2009-04-16 16:12     ` patrick.gunia
  0 siblings, 1 reply; 12+ messages in thread
From: Adam Beneschan @ 2009-04-16 16:01 UTC (permalink / raw)


On Apr 16, 8:50 am, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
> Hi Patrick,
>
> Why don't you pass the outer array as an "in out" parameter to your
> subprogram and let the subprogram write directly into the array?

I get the impression that the OP wanted an array of class-wide types,
so this won't work.

                              -- Adam




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

* Re: Problems with Scope of aliased Objects
  2009-04-16 16:01   ` Adam Beneschan
@ 2009-04-16 16:12     ` patrick.gunia
  2009-04-17 13:53       ` Alex R. Mosteo
  0 siblings, 1 reply; 12+ messages in thread
From: patrick.gunia @ 2009-04-16 16:12 UTC (permalink / raw)


On 16 Apr., 18:01, Adam Beneschan <a...@irvine.com> wrote:
> On Apr 16, 8:50 am, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
>
> > Hi Patrick,
>
> > Why don't you pass the outer array as an "in out" parameter to your
> > subprogram and let the subprogram write directly into the array?
>
> I get the impression that the OP wanted an array of class-wide types,
> so this won't work.
>
>                               -- Adam

Yes, this is exactly what I need. I´d like to use the elements of the
array for polymorphic methods and the array has to be able to keep
members from different classes within my hierarchie. Thus I won´t have
another option then declaring the array as an array of class-wide
access types. So this part is fixed. In Ludovic´s approach I would
still work with concrete instances of my class, which won´t work for
my structure.



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 15:59   ` patrick.gunia
@ 2009-04-16 16:26     ` Adam Beneschan
  2009-04-16 16:37       ` patrick.gunia
  2009-04-16 20:11       ` Adam Beneschan
  0 siblings, 2 replies; 12+ messages in thread
From: Adam Beneschan @ 2009-04-16 16:26 UTC (permalink / raw)


On Apr 16, 8:59 am, "patrick.gu...@googlemail.com"
> Alright, this was my explanation. I forgot the fact, that the values
> are copied into the array. The simple reason why I didn´t want to use
> heap-memory is the performance-aspect. My third approach works using
> "new" to allocate heap-memory dynamically. In this case, adding the
> access-type into the array leads to a copy of the heap-memory-adress
> where the object was created. This address is copied into the array
> and thus still reachable. To cut a long story short, my second
> approach simply won´t work because of dangling pointers which point to
> memory which isn´t assigned any longer (at least not to the objects I
> expect to be there). Do I have to be afraid of runtime-performance-
> problems when using dynamic allocation in Ada?

I don't know.  That will depend on which implementation of Ada you use
and just what your performance requirements are.  If it's really a
concern, you can set up your own storage pool, with your own
allocation and deallocation routines, and tell the compiler that any
time you use "new" for certain access types, they will use that pool.
Then you can optimize the pool routines and tailor them to the
specific way you will use it (for example, if you never deallocate
anything, you can take advantage of that fact to simply the Allocate
routine; or you can organize the pool so that all objects of the same
size will be next to each other, which could lead to a more efficient
implementation).  Storage pools are explained in 13.11 of the RM, and
there may be other helpful resources, and I'm sure there are publicly
available examples of storage pools that you can use or modify---but I
don't know where they are, so hopefully someone else can point you to
them.

                              -- Adam




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

* Re: Problems with Scope of aliased Objects
  2009-04-16 16:26     ` Adam Beneschan
@ 2009-04-16 16:37       ` patrick.gunia
  2009-04-16 20:11       ` Adam Beneschan
  1 sibling, 0 replies; 12+ messages in thread
From: patrick.gunia @ 2009-04-16 16:37 UTC (permalink / raw)


On 16 Apr., 18:26, Adam Beneschan <a...@irvine.com> wrote:
> On Apr 16, 8:59 am, "patrick.gu...@googlemail.com"
>
> > Alright, this was my explanation. I forgot the fact, that the values
> > are copied into the array. The simple reason why I didn´t want to use
> > heap-memory is the performance-aspect. My third approach works using
> > "new" to allocate heap-memory dynamically. In this case, adding the
> > access-type into the array leads to a copy of the heap-memory-adress
> > where the object was created. This address is copied into the array
> > and thus still reachable. To cut a long story short, my second
> > approach simply won´t work because of dangling pointers which point to
> > memory which isn´t assigned any longer (at least not to the objects I
> > expect to be there). Do I have to be afraid of runtime-performance-
> > problems when using dynamic allocation in Ada?
>
> I don't know.  That will depend on which implementation of Ada you use
> and just what your performance requirements are.  If it's really a
> concern, you can set up your own storage pool, with your own
> allocation and deallocation routines, and tell the compiler that any
> time you use "new" for certain access types, they will use that pool.
> Then you can optimize the pool routines and tailor them to the
> specific way you will use it (for example, if you never deallocate
> anything, you can take advantage of that fact to simply the Allocate
> routine; or you can organize the pool so that all objects of the same
> size will be next to each other, which could lead to a more efficient
> implementation).  Storage pools are explained in 13.11 of the RM, and
> there may be other helpful resources, and I'm sure there are publicly
> available examples of storage pools that you can use or modify---but I
> don't know where they are, so hopefully someone else can point you to
> them.
>
>                               -- Adam

Alright, then I think I´ll search some ressources concerning storage
pools. I use GNAT 3.4.5 (mingw-vista special r3) with Ada95. Indeed I
deal with a situation in which the dynamic-allocation is performed
while initializing the software and freed when shutting it down. Thus
I usually don´t have to deallocate the dynamically allocated memory as
the runtime-system frees it at program-shutdown. This might be a
starting-point for optimization.
Thank you!



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 15:47 ` Dmitry A. Kazakov
@ 2009-04-16 19:12   ` sjw
  0 siblings, 0 replies; 12+ messages in thread
From: sjw @ 2009-04-16 19:12 UTC (permalink / raw)


On Apr 16, 4:47 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> Fourth solution could be to use a container of unconstrained objects or a
> container of smart pointers if the objects are limited.

ie, instantiate Ada.Containers.Indefinite_Vectors (http://
www.adaic.com/standards/05rm/html/RM-A-18-10.html) .. or lists, maps,
sets, as needed .. with type Foo'Class.

Of course this has to do heap allocation behind the scenes, but you
don't have to worry about it yourself unless performance is really an
issue. If you think it might be an issue, write a performance spec and
do some measurements before you start optimising!



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 16:26     ` Adam Beneschan
  2009-04-16 16:37       ` patrick.gunia
@ 2009-04-16 20:11       ` Adam Beneschan
  1 sibling, 0 replies; 12+ messages in thread
From: Adam Beneschan @ 2009-04-16 20:11 UTC (permalink / raw)


On Apr 16, 9:26 am, Adam Beneschan <a...@irvine.com> wrote:

> Then you can optimize the pool routines and tailor them to the
> specific way you will use it (for example, if you never deallocate
> anything, you can take advantage of that fact to simply the Allocate
> routine

that should have been "simplify the Allocate routine"...

                                -- Adam



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

* Re: Problems with Scope of aliased Objects
  2009-04-16 16:12     ` patrick.gunia
@ 2009-04-17 13:53       ` Alex R. Mosteo
  0 siblings, 0 replies; 12+ messages in thread
From: Alex R. Mosteo @ 2009-04-17 13:53 UTC (permalink / raw)


patrick.gunia@googlemail.com wrote:

> On 16 Apr., 18:01, Adam Beneschan <a...@irvine.com> wrote:
>> On Apr 16, 8:50 am, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
>>
>> > Hi Patrick,
>>
>> > Why don't you pass the outer array as an "in out" parameter to your
>> > subprogram and let the subprogram write directly into the array?
>>
>> I get the impression that the OP wanted an array of class-wide types,
>> so this won't work.
>>
>> -- Adam
> 
> Yes, this is exactly what I need. I´d like to use the elements of the
> array for polymorphic methods and the array has to be able to keep
> members from different classes within my hierarchie. Thus I won´t have
> another option then declaring the array as an array of class-wide
> access types. So this part is fixed. In Ludovic´s approach I would
> still work with concrete instances of my class, which won´t work for
> my structure.

You could also use the indefinite vectors from the 2005 standard library, if 
your compiler has it already. That way you don't need to deal with access 
types and the heap directly.




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

end of thread, other threads:[~2009-04-17 13:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-16 13:43 Problems with Scope of aliased Objects patrick.gunia
2009-04-16 15:29 ` Adam Beneschan
2009-04-16 15:59   ` patrick.gunia
2009-04-16 16:26     ` Adam Beneschan
2009-04-16 16:37       ` patrick.gunia
2009-04-16 20:11       ` Adam Beneschan
2009-04-16 15:47 ` Dmitry A. Kazakov
2009-04-16 19:12   ` sjw
2009-04-16 15:50 ` Ludovic Brenta
2009-04-16 16:01   ` Adam Beneschan
2009-04-16 16:12     ` patrick.gunia
2009-04-17 13:53       ` Alex R. Mosteo

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