comp.lang.ada
 help / color / mirror / Atom feed
* Error: "non-local pointer cannot point to a local object"
@ 2018-09-11 22:20 NiGHTS
  2018-09-12  1:49 ` Brad Moore
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: NiGHTS @ 2018-09-11 22:20 UTC (permalink / raw)


As the subject line indicates, I am having a compile error which I am having difficulty solving.

I have two distinct records, in this example called "Master_Record" and "Working_Record". One contains an Integer, the other a "pointer" to that Integer. In this context, Working_Record depends on Master_Record. There can be many Working_Record instances for a single Master_Record. The Copy function is intended to enforce this rule by acting as an object factory, requiring an instance of Master_Record to create Working_Record. I know this isn't perfect, so any suggestions on a better strategy would be appreciated.

Ultimately the purpose of this is for Working_Record to be a copy-friendly record, where Master_Record is not intended to be used directly, except as a place to anchor the variable scope. The resulting code will be written as a library object containing two records just like I have here, as well as a Copy function. The user of this library object is expected to create an instance of Master_Record, then copy it to Working_Record. 

----------------------------------------
type Master_Record is record
        
        Root  : aliased Integer;
        -- Here is where other general variables are kept
                
end record;
                
type Working_Record is record
        
        Root_Pointer    : access Integer;
        -- Here is where specific instance variables are kept
                
end record;
                
function Copy (
                
        Source : in out Master_Record
                        
) return Working_Record is
begin
                
        return (Root_Pointer => Source.Root'Access); -- << Error here >>
                
end Copy;
                
MR : Master_Record;
WR : Working_Record := Copy (MR);  
----------------------------------------

Any ideas on how to achieve this goal? I'm sure its something simple. Thanks in advance!


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

* Re: Error: "non-local pointer cannot point to a local object"
  2018-09-11 22:20 Error: "non-local pointer cannot point to a local object" NiGHTS
@ 2018-09-12  1:49 ` Brad Moore
  2018-09-12 14:41   ` NiGHTS
  2018-09-12  6:05 ` rakusu_klein
  2018-09-12  7:26 ` Dmitry A. Kazakov
  2 siblings, 1 reply; 8+ messages in thread
From: Brad Moore @ 2018-09-12  1:49 UTC (permalink / raw)


On Tuesday, September 11, 2018 at 4:21:00 PM UTC-6, NiGHTS wrote:
> As the subject line indicates, I am having a compile error which I am having difficulty solving.
> 
> I have two distinct records, in this example called "Master_Record" and "Working_Record". One contains an Integer, the other a "pointer" to that Integer. In this context, Working_Record depends on Master_Record. There can be many Working_Record instances for a single Master_Record. The Copy function is intended to enforce this rule by acting as an object factory, requiring an instance of Master_Record to create Working_Record. I know this isn't perfect, so any suggestions on a better strategy would be appreciated.
> 
> Ultimately the purpose of this is for Working_Record to be a copy-friendly record, where Master_Record is not intended to be used directly, except as a place to anchor the variable scope. The resulting code will be written as a library object containing two records just like I have here, as well as a Copy function. The user of this library object is expected to create an instance of Master_Record, then copy it to Working_Record. 
> 
> ----------------------------------------
> type Master_Record is record
>         
>         Root  : aliased Integer;
>         -- Here is where other general variables are kept
>                 
> end record;
>                 
> type Working_Record is record
>         
>         Root_Pointer    : access Integer;
>         -- Here is where specific instance variables are kept
>                 
> end record;
>                 
> function Copy (
>                 
>         Source : in out Master_Record
>                         
> ) return Working_Record is
> begin
>                 
>         return (Root_Pointer => Source.Root'Access); -- << Error here >>
>                 
> end Copy;
>                 
> MR : Master_Record;
> WR : Working_Record := Copy (MR);  
> ----------------------------------------
> 
> Any ideas on how to achieve this goal? I'm sure its something simple. Thanks in advance!

One solution would be to use access discriminants.


eg.
package P is
                
   type Master_Record is record 
        
      Root  : aliased Integer; 
      -- Here is where other general variables are kept 
                
   end record; 
   
   type Working_Record (Root : not null access Integer) is record 
      null;
      -- Here is where specific instance variables are kept 
   end record; 
   
end P;

with P; use P;

procedure Main is
   MR : aliased Master_Record;
   WR1 : Working_Record (Root => MR.Root'Access);
   WR2 : Working_Record (Root => MR.Root'Access);
begin   
   WR1.Root.all := 35;
   WR2.Root.all := 36;
end Main;

regards,

Brad


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

* Re: Error: "non-local pointer cannot point to a local object"
  2018-09-11 22:20 Error: "non-local pointer cannot point to a local object" NiGHTS
  2018-09-12  1:49 ` Brad Moore
@ 2018-09-12  6:05 ` rakusu_klein
  2018-09-12 14:42   ` NiGHTS
  2018-09-12  7:26 ` Dmitry A. Kazakov
  2 siblings, 1 reply; 8+ messages in thread
From: rakusu_klein @ 2018-09-12  6:05 UTC (permalink / raw)


For Access attribute compiler checks if the object itself will live as long as an access to it for preventing "dangling reference". For situations when you take control over pointers in your hands, you must use the Unchecked_Access attribute. See ARM95 13.10 for details.

P.S.: Sorry for google translate.


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

* Re: Error: "non-local pointer cannot point to a local object"
  2018-09-11 22:20 Error: "non-local pointer cannot point to a local object" NiGHTS
  2018-09-12  1:49 ` Brad Moore
  2018-09-12  6:05 ` rakusu_klein
@ 2018-09-12  7:26 ` Dmitry A. Kazakov
  2018-09-12 14:47   ` NiGHTS
  2 siblings, 1 reply; 8+ messages in thread
From: Dmitry A. Kazakov @ 2018-09-12  7:26 UTC (permalink / raw)


On 2018-09-12 00:20, NiGHTS wrote:
> As the subject line indicates, I am having a compile error which I am having difficulty solving.
> 
> I have two distinct records, in this example called "Master_Record" and "Working_Record". One contains an Integer, the other a "pointer" to that Integer. In this context, Working_Record depends on Master_Record. There can be many Working_Record instances for a single Master_Record. The Copy function is intended to enforce this rule by acting as an object factory, requiring an instance of Master_Record to create Working_Record. I know this isn't perfect, so any suggestions on a better strategy would be appreciated.
> 
> Ultimately the purpose of this is for Working_Record to be a copy-friendly record, where Master_Record is not intended to be used directly, except as a place to anchor the variable scope. The resulting code will be written as a library object containing two records just like I have here, as well as a Copy function. The user of this library object is expected to create an instance of Master_Record, then copy it to Working_Record.
> 
> ----------------------------------------
> type Master_Record is record
>          
>          Root  : aliased Integer;
>          -- Here is where other general variables are kept
>                  
> end record;
>                  
> type Working_Record is record
>          
>          Root_Pointer    : access Integer;
>          -- Here is where specific instance variables are kept
>                  
> end record;
>                  
> function Copy (
>                  
>          Source : in out Master_Record
>                          
> ) return Working_Record is
> begin
>                  
>          return (Root_Pointer => Source.Root'Access); -- << Error here >>

What about killing accessibility info:

    return (Root_Pointer => Source.Root.all'Unchecked_Access);

> end Copy;
>                  
> MR : Master_Record;
> WR : Working_Record := Copy (MR);
> ----------------------------------------
> 
> Any ideas on how to achieve this goal? I'm sure its something simple. Thanks in advance!

What goal? It looks like a bad design. Copying pointers to integers is 
asking for trouble.

BTW, if you used Ada.Finalization.Controlled, as you likely should, and 
derived one record from another then default copying before Adjust would 
copy pointer too. What would happen with access info, I have no idea, 
probably copied as-is. (Yet another reason not to use anonymous access 
types inside records unless for Rosen's trick or access-to-constant)

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

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

* Re: Error: "non-local pointer cannot point to a local object"
  2018-09-12  1:49 ` Brad Moore
@ 2018-09-12 14:41   ` NiGHTS
  0 siblings, 0 replies; 8+ messages in thread
From: NiGHTS @ 2018-09-12 14:41 UTC (permalink / raw)


On Tuesday, September 11, 2018 at 9:49:44 PM UTC-4, Brad Moore wrote:
> On Tuesday, September 11, 2018 at 4:21:00 PM UTC-6, NiGHTS wrote:
> > As the subject line indicates, I am having a compile error which I am having difficulty solving.
> > 
> > I have two distinct records, in this example called "Master_Record" and "Working_Record". One contains an Integer, the other a "pointer" to that Integer. In this context, Working_Record depends on Master_Record. There can be many Working_Record instances for a single Master_Record. The Copy function is intended to enforce this rule by acting as an object factory, requiring an instance of Master_Record to create Working_Record. I know this isn't perfect, so any suggestions on a better strategy would be appreciated.
> > 
> > Ultimately the purpose of this is for Working_Record to be a copy-friendly record, where Master_Record is not intended to be used directly, except as a place to anchor the variable scope. The resulting code will be written as a library object containing two records just like I have here, as well as a Copy function. The user of this library object is expected to create an instance of Master_Record, then copy it to Working_Record. 
> > 
> > ----------------------------------------
> > type Master_Record is record
> >         
> >         Root  : aliased Integer;
> >         -- Here is where other general variables are kept
> >                 
> > end record;
> >                 
> > type Working_Record is record
> >         
> >         Root_Pointer    : access Integer;
> >         -- Here is where specific instance variables are kept
> >                 
> > end record;
> >                 
> > function Copy (
> >                 
> >         Source : in out Master_Record
> >                         
> > ) return Working_Record is
> > begin
> >                 
> >         return (Root_Pointer => Source.Root'Access); -- << Error here >>
> >                 
> > end Copy;
> >                 
> > MR : Master_Record;
> > WR : Working_Record := Copy (MR);  
> > ----------------------------------------
> > 
> > Any ideas on how to achieve this goal? I'm sure its something simple. Thanks in advance!
> 
> One solution would be to use access discriminants.
> 
> 
> eg.
> package P is
>                 
>    type Master_Record is record 
>         
>       Root  : aliased Integer; 
>       -- Here is where other general variables are kept 
>                 
>    end record; 
>    
>    type Working_Record (Root : not null access Integer) is record 
>       null;
>       -- Here is where specific instance variables are kept 
>    end record; 
>    
> end P;
> 
> with P; use P;
> 
> procedure Main is
>    MR : aliased Master_Record;
>    WR1 : Working_Record (Root => MR.Root'Access);
>    WR2 : Working_Record (Root => MR.Root'Access);
> begin   
>    WR1.Root.all := 35;
>    WR2.Root.all := 36;
> end Main;
> 
> regards,
> 
> Brad

I like this strategy as it enforces my dependency requirement. Thank you.


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

* Re: Error: "non-local pointer cannot point to a local object"
  2018-09-12  6:05 ` rakusu_klein
@ 2018-09-12 14:42   ` NiGHTS
  0 siblings, 0 replies; 8+ messages in thread
From: NiGHTS @ 2018-09-12 14:42 UTC (permalink / raw)


On Wednesday, September 12, 2018 at 2:05:08 AM UTC-4, rakusu...@fastmail.jp wrote:
> For Access attribute compiler checks if the object itself will live as long as an access to it for preventing "dangling reference". For situations when you take control over pointers in your hands, you must use the Unchecked_Access attribute. See ARM95 13.10 for details.
> 
> P.S.: Sorry for google translate.

Yes, I had forgotten about that attribute. That could also work for me. Thank you.

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

* Re: Error: "non-local pointer cannot point to a local object"
  2018-09-12  7:26 ` Dmitry A. Kazakov
@ 2018-09-12 14:47   ` NiGHTS
  2018-09-12 15:22     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 8+ messages in thread
From: NiGHTS @ 2018-09-12 14:47 UTC (permalink / raw)


On Wednesday, September 12, 2018 at 3:26:46 AM UTC-4, Dmitry A. Kazakov wrote:

> What goal? It looks like a bad design. Copying pointers to integers is 
> asking for trouble.

The integer was chosen to simplify the example. In the actual application it is a tree container, where there is a single thread that is expected to manipulate various contexts of the same tree, thus multiple working records for the same tree.

> 
> BTW, if you used Ada.Finalization.Controlled, as you likely should, and 
> derived one record from another then default copying before Adjust would 
> copy pointer too. What would happen with access info, I have no idea, 
> probably copied as-is. (Yet another reason not to use anonymous access 
> types inside records unless for Rosen's trick or access-to-constant)
> 
While my example does not show Ada.Finalization.Controlled in use, my application's record indeed is derived from this object. Still, I am not sure how overriding Adjust would be applied to my example. Would you show me a quick and dirty example of how this would be done?

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

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

* Re: Error: "non-local pointer cannot point to a local object"
  2018-09-12 14:47   ` NiGHTS
@ 2018-09-12 15:22     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 8+ messages in thread
From: Dmitry A. Kazakov @ 2018-09-12 15:22 UTC (permalink / raw)


On 2018-09-12 16:47, NiGHTS wrote:
> On Wednesday, September 12, 2018 at 3:26:46 AM UTC-4, Dmitry A. Kazakov wrote:
> 
>> What goal? It looks like a bad design. Copying pointers to integers is
>> asking for trouble.
> 
> The integer was chosen to simplify the example. In the actual application it is a tree container, where there is a single thread that is expected to manipulate various contexts of the same tree, thus multiple working records for the same tree.

Why do you need copying? By-reference semantics does not match copying 
(= by-value).

>> BTW, if you used Ada.Finalization.Controlled, as you likely should, and
>> derived one record from another then default copying before Adjust would
>> copy pointer too. What would happen with access info, I have no idea,
>> probably copied as-is. (Yet another reason not to use anonymous access
>> types inside records unless for Rosen's trick or access-to-constant)
>>
> While my example does not show Ada.Finalization.Controlled in use, my application's record indeed is derived from this object. Still, I am not sure how overriding Adjust would be applied to my example. Would you show me a quick and dirty example of how this would be done?

Before Adjust is called an exact copy of the controlled source object is 
made. This naturally applies to its access components as well. Thus you 
probably need not to override Adjust at all.

[ As I said I don't know what happens with the accessibility checks. 
Where assignment of plain records fail, would assignment of controlled 
ones fail as well, if Adjust is null? ]

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


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

end of thread, other threads:[~2018-09-12 15:22 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-11 22:20 Error: "non-local pointer cannot point to a local object" NiGHTS
2018-09-12  1:49 ` Brad Moore
2018-09-12 14:41   ` NiGHTS
2018-09-12  6:05 ` rakusu_klein
2018-09-12 14:42   ` NiGHTS
2018-09-12  7:26 ` Dmitry A. Kazakov
2018-09-12 14:47   ` NiGHTS
2018-09-12 15:22     ` Dmitry A. Kazakov

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