comp.lang.ada
 help / color / mirror / Atom feed
* strange cursor in nested containers
@ 2023-04-19  7:09 Mario Blunk
  2023-04-19 15:07 ` Simon Wright
  2023-04-20  5:15 ` Egil H H
  0 siblings, 2 replies; 13+ messages in thread
From: Mario Blunk @ 2023-04-19  7:09 UTC (permalink / raw)


Hello out there,
I've put together a demo to reproduce a strange behavior of a cursor.

https://github.com/Blunk-electronic/ada_training/blob/master/src/containers/demo/nested/nest_1.adb

Description:
Inside the procedure "get_line" the cursor "result" is assigned only once (on match). Since there is no further match, in the course of the procedure, I assume that "result" is never changed. So the expected output should be:

net: A
L1 S: 2.00000E+00 E: 3.00000E+00
L2 S: 2.00000E+00 E: 3.00000E+00
net: B
L2 S: 2.00000E+00 E: 3.00000E+00
L3 S: 2.00000E+00 E: 3.00000E+00

but the actual output is:

net: A
L1 S: 2.00000E+00 E: 3.00000E+00
L2 S: 2.00000E+00 E: 3.00000E+00
net: B
L2 S: 1.20000E+01 E: 1.30000E+01
L3 S: 7.47956E-39 E: 0.00000E+00 -- changes randomly

Thanks for your help.


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

* Re: strange cursor in nested containers
  2023-04-19  7:09 strange cursor in nested containers Mario Blunk
@ 2023-04-19 15:07 ` Simon Wright
  2023-04-20  5:15 ` Egil H H
  1 sibling, 0 replies; 13+ messages in thread
From: Simon Wright @ 2023-04-19 15:07 UTC (permalink / raw)


Mario Blunk <mario.blunk.gplus@gmail.com> writes:

> I've put together a demo to reproduce a strange behavior of a cursor.
>
> https://github.com/Blunk-electronic/ada_training/blob/master/src/containers/demo/nested/nest_1.adb
>
> Description:
> Inside the procedure "get_line" the cursor "result" is assigned only
> once (on match). Since there is no further match, in the course of the
> procedure, I assume that "result" is never changed. So the expected
> output should be:
>
> net: A
> L1 S: 2.00000E+00 E: 3.00000E+00
> L2 S: 2.00000E+00 E: 3.00000E+00
> net: B
> L2 S: 2.00000E+00 E: 3.00000E+00
> L3 S: 2.00000E+00 E: 3.00000E+00
>
> but the actual output is:
>
> net: A
> L1 S: 2.00000E+00 E: 3.00000E+00
> L2 S: 2.00000E+00 E: 3.00000E+00
> net: B
> L2 S: 1.20000E+01 E: 1.30000E+01
> L3 S: 7.47956E-39 E: 0.00000E+00 -- changes randomly

This is a puzzler.

To simplify matters (for me, anyway) I changed your doubly linked list
to a vector. Now, instead of junk, I get an access violation.

'result' isn't changed, but a Cursor contains a pointer to the container
and an index; using gdb to look at the container via the unchanged
pointer, it's been overwritten with garbage. However, looping with this
(after the Nets.Iterate call, i.e. after Result has been damaged)

      for N of Nets loop
         for TL of N.Lines loop
            Put_Line (To_String (TL));
         end loop;
      end loop;

works just fine.

My head hurts.

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

* Re: strange cursor in nested containers
  2023-04-19  7:09 strange cursor in nested containers Mario Blunk
  2023-04-19 15:07 ` Simon Wright
@ 2023-04-20  5:15 ` Egil H H
  2023-04-20  5:33   ` Egil H H
  2023-04-20 14:59   ` Simon Wright
  1 sibling, 2 replies; 13+ messages in thread
From: Egil H H @ 2023-04-20  5:15 UTC (permalink / raw)


On Wednesday, April 19, 2023 at 9:09:48 AM UTC+2, Mario Blunk wrote:
> Hello out there, 
> I've put together a demo to reproduce a strange behavior of a cursor. 
> 
> https://github.com/Blunk-electronic/ada_training/blob/master/src/containers/demo/nested/nest_1.adb 
> 

Each call to `element(n)` returns a _copy_ of the element, which in this case includes the enitre doubly linked list
(and since `net` is a renames of `element(n), you would have gotten multiple copies if you had called `net` multiple times inside query net)

Using a reference instead should fix this problem:
			net : type_net renames nets.reference (key(n));

or (Ada 2012):
			net : type_net renames nets(n);

-- 
~egilhh

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

* Re: strange cursor in nested containers
  2023-04-20  5:15 ` Egil H H
@ 2023-04-20  5:33   ` Egil H H
  2023-04-20 14:59   ` Simon Wright
  1 sibling, 0 replies; 13+ messages in thread
From: Egil H H @ 2023-04-20  5:33 UTC (permalink / raw)


On Thursday, April 20, 2023 at 7:15:36 AM UTC+2, Egil H H wrote:
> On Wednesday, April 19, 2023 at 9:09:48 AM UTC+2, Mario Blunk wrote: 
> 
> Using a reference instead should fix this problem: 
> net : type_net renames nets.reference (key(n)); 
> 
> or (Ada 2012): 
> net : type_net renames nets(n); 
> 

oops, both my solutions are Ada 2012 :)

If Ada 2005 is a requirement (based on your explicit usage of `iterate`), I guess you would need an extra set of callbacks and call `update_element` in order to get a reference to the element containing the correct instance of the doubly linked list

-- 
~egilhh

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

* Re: strange cursor in nested containers
  2023-04-20  5:15 ` Egil H H
  2023-04-20  5:33   ` Egil H H
@ 2023-04-20 14:59   ` Simon Wright
  2023-04-20 15:28     ` Mario Blunk
  1 sibling, 1 reply; 13+ messages in thread
From: Simon Wright @ 2023-04-20 14:59 UTC (permalink / raw)


Egil H H <ehh.public@gmail.com> writes:

> Each call to `element(n)` returns a _copy_ of the element, which in
> this case includes the enitre doubly linked list

This is indeed the problem, thanks!

I hadn't considered the effect of renaming a function call; the cursor
constructed inside query_net refers to the locally renamed copy of
type_net, which will be destroyed on exit from query_net.

>                                                  (and since `net` is a
> renames of `element(n), you would have gotten multiple copies if you
> had called `net` multiple times inside query net)

This appears to say that this renaming of a function call results in
something like a macro, but I think that

   R : T renames Func;

is more like

   R : constant T := Func;
   
ARM 8.5(3) says

   "The elaboration of a renaming_declaration evaluates the name that
   follows the reserved word renames and thereby determines the view and
   entity denoted by this name (the renamed view and renamed entity). A
   name that denotes the renaming_declaration denotes (a new view of)
   the renamed entity."

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

* Re: strange cursor in nested containers
  2023-04-20 14:59   ` Simon Wright
@ 2023-04-20 15:28     ` Mario Blunk
  2023-04-22  9:33       ` Randy Brukardt
  0 siblings, 1 reply; 13+ messages in thread
From: Mario Blunk @ 2023-04-20 15:28 UTC (permalink / raw)


Thanks for your replies. Now it is becoming clear to me:

1. The statement net : type_net renames element (n) gives a copy of element (n).
2. After the assignment to "result" (line 55), "result" points to an element inside the local copy "net".
3. Once "net" is overwritten in the next call of query_net, "result" still refers to a "net" that does not exist anymore. Likewise, once procedure query_net is left, "result" still points to a list that does not exist anymore. Thatswhy I get garbage in line 68 and 77.
Correct ?



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

* Re: strange cursor in nested containers
  2023-04-20 15:28     ` Mario Blunk
@ 2023-04-22  9:33       ` Randy Brukardt
  2023-04-22 17:04         ` Mario Blunk
  0 siblings, 1 reply; 13+ messages in thread
From: Randy Brukardt @ 2023-04-22  9:33 UTC (permalink / raw)


I agree. If you used a debugging container that checked for dangling 
cursors, you probably would have gotten an exception from any use of the 
cursor to the dead copy. Not sure that would have been any clearer as to the 
cause, but it would be a suggestion. (Not sure if GNAT still has debugging 
containers, they did at one point, but a lot of work has been done on them 
since.)

              Randy.

"Mario Blunk" <mario.blunk.gplus@gmail.com> wrote in message 
news:ed311a62-41ba-493e-a4cc-481402a1cc6bn@googlegroups.com...
Thanks for your replies. Now it is becoming clear to me:

1. The statement net : type_net renames element (n) gives a copy of element 
(n).
2. After the assignment to "result" (line 55), "result" points to an element 
inside the local copy "net".
3. Once "net" is overwritten in the next call of query_net, "result" still 
refers to a "net" that does not exist anymore. Likewise, once procedure 
query_net is left, "result" still points to a list that does not exist 
anymore. Thatswhy I get garbage in line 68 and 77.
Correct ?




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

* Re: strange cursor in nested containers
  2023-04-22  9:33       ` Randy Brukardt
@ 2023-04-22 17:04         ` Mario Blunk
  2023-04-22 18:33           ` Jeffrey R.Carter
  0 siblings, 1 reply; 13+ messages in thread
From: Mario Blunk @ 2023-04-22 17:04 UTC (permalink / raw)


I wonder why at runtime no exception is raised.
How could I solve the problem ? Not using "rename" ? Using an aliased access type as John Barnes suggests in Ada2005 on page 275 ?

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

* Re: strange cursor in nested containers
  2023-04-22 17:04         ` Mario Blunk
@ 2023-04-22 18:33           ` Jeffrey R.Carter
  2023-04-25  7:30             ` Mario Blunk
  0 siblings, 1 reply; 13+ messages in thread
From: Jeffrey R.Carter @ 2023-04-22 18:33 UTC (permalink / raw)


On 2023-04-22 19:04, Mario Blunk wrote:
> I wonder why at runtime no exception is raised.
> How could I solve the problem ? Not using "rename" ? Using an aliased access type as John Barnes suggests in Ada2005 on page 275 ?

You have to avoid calling Element. Since you have a cursor, you can call 
Query_Element, which should pass the actual element to the procedure you supply.

-- 
Jeff Carter
"He didn't get that nose from playing ping-pong."
Never Give a Sucker an Even Break
110

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

* Re: strange cursor in nested containers
  2023-04-22 18:33           ` Jeffrey R.Carter
@ 2023-04-25  7:30             ` Mario Blunk
  2023-05-09  3:56               ` Randy Brukardt
  0 siblings, 1 reply; 13+ messages in thread
From: Mario Blunk @ 2023-04-25  7:30 UTC (permalink / raw)


> > How could I solve the problem ? Not using "rename" ? Using an aliased access type as John Barnes suggests in Ada2005 on page 275 ?
> You have to avoid calling Element. Since you have a cursor, you can call 
> Query_Element, which should pass the actual element to the procedure you supply. 

Right, that solves the problem. For those interested please find a comparison here:

1. The demo with a dangling (dangerous) cursor:
https://github.com/Blunk-electronic/ada_training/blob/master/src/containers/demo/nested/nest_1.adb

And the demo with the issue solved properly:
https://github.com/Blunk-electronic/ada_training/blob/master/src/containers/demo/nested/nest_2.adb

Still the question remains, why such a dangling cursor is not detected at runtime.

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

* Re: strange cursor in nested containers
  2023-04-25  7:30             ` Mario Blunk
@ 2023-05-09  3:56               ` Randy Brukardt
  2023-05-09  8:36                 ` Jeffrey R.Carter
  0 siblings, 1 reply; 13+ messages in thread
From: Randy Brukardt @ 2023-05-09  3:56 UTC (permalink / raw)


It's not required to detect such cursors because it is expensive to do so 
perfectly (essentially, each cursor has to be controlled and one has to keep 
a list of them associated with the container). There are imperfect solutions 
which are likely to be "good enough" in practice, but they still have a 
(small) cost which may be an issue for some uses. Thus, most implementers 
don't use them. I know the original GNAT containers had a debugging version 
that included such checks, but I don't know if they still exist or how one 
would enable them if they do.

            Randy.

"Mario Blunk" <mario.blunk.gplus@gmail.com> wrote in message 
news:9a1c3ba5-d5ae-41d3-9eab-2b8cd941bc66n@googlegroups.com...
>> > How could I solve the problem ? Not using "rename" ? Using an aliased 
>> > access type as John Barnes suggests in Ada2005 on page 275 ?
>> You have to avoid calling Element. Since you have a cursor, you can call
>> Query_Element, which should pass the actual element to the procedure you 
>> supply.
>
> Right, that solves the problem. For those interested please find a 
> comparison here:
>
> 1. The demo with a dangling (dangerous) cursor:
> https://github.com/Blunk-electronic/ada_training/blob/master/src/containers/demo/nested/nest_1.adb
>
> And the demo with the issue solved properly:
> https://github.com/Blunk-electronic/ada_training/blob/master/src/containers/demo/nested/nest_2.adb
>
> Still the question remains, why such a dangling cursor is not detected at 
> runtime. 


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

* Re: strange cursor in nested containers
  2023-05-09  3:56               ` Randy Brukardt
@ 2023-05-09  8:36                 ` Jeffrey R.Carter
  2023-05-09  8:49                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 13+ messages in thread
From: Jeffrey R.Carter @ 2023-05-09  8:36 UTC (permalink / raw)


On 2023-05-09 05:56, Randy Brukardt wrote:
> It's not required to detect such cursors because it is expensive to do so
> perfectly (essentially, each cursor has to be controlled and one has to keep
> a list of them associated with the container). There are imperfect solutions
> which are likely to be "good enough" in practice, but they still have a
> (small) cost which may be an issue for some uses. Thus, most implementers
> don't use them. I know the original GNAT containers had a debugging version
> that included such checks, but I don't know if they still exist or how one
> would enable them if they do.

This cost is due to the decision to allow access to elements using only a 
cursor. If both the container and the cursor are needed, then the cost is 
significantly reduced. This is the approach that was used in the Ada-95 version 
of the PragmAda Reusable Components.

-- 
Jeff Carter
“Bug rates in C++ are running higher even than C ...”
Stephen F. Zeigler
216

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

* Re: strange cursor in nested containers
  2023-05-09  8:36                 ` Jeffrey R.Carter
@ 2023-05-09  8:49                   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2023-05-09  8:49 UTC (permalink / raw)


On 2023-05-09 10:36, Jeffrey R.Carter wrote:

> This cost is due to the decision to allow access to elements using only 
> a cursor. If both the container and the cursor are needed, then the cost 
> is significantly reduced.

That would be in the index/position team rather than in the 
cursor/pointer/address one.

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

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

end of thread, other threads:[~2023-05-09  8:49 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-19  7:09 strange cursor in nested containers Mario Blunk
2023-04-19 15:07 ` Simon Wright
2023-04-20  5:15 ` Egil H H
2023-04-20  5:33   ` Egil H H
2023-04-20 14:59   ` Simon Wright
2023-04-20 15:28     ` Mario Blunk
2023-04-22  9:33       ` Randy Brukardt
2023-04-22 17:04         ` Mario Blunk
2023-04-22 18:33           ` Jeffrey R.Carter
2023-04-25  7:30             ` Mario Blunk
2023-05-09  3:56               ` Randy Brukardt
2023-05-09  8:36                 ` Jeffrey R.Carter
2023-05-09  8:49                   ` 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