comp.lang.ada
 help / color / mirror / Atom feed
* debugging tool?
@ 2004-02-21  5:56 tmoran
  2004-02-22 21:25 ` Hyman Rosen
  0 siblings, 1 reply; 9+ messages in thread
From: tmoran @ 2004-02-21  5:56 UTC (permalink / raw)


Is there a tool around that would scan a large program to check for
instances of an object being accessed *after* it's been Finalized?
As in this program, where two compilers happily allow just that for
Helper, and a third doesn't, but gives no error message.

with ada.finalization;
package testff1 is
  type A is new ada.finalization.controlled with null record;
  procedure Finalize(x : in out A);
  AA : A;
private
  type Helper_Type(id : integer) is new ada.finalization.controlled with null record;
  procedure Finalize(x : in out Helper_Type);
  procedure dummy(x : in out Helper_Type);
end testff1;

with ada.text_io;
package body testff1 is

  Helper : Helper_Type(1);

  procedure Finalize(x : in out Helper_Type) is
  begin
    ada.text_io.put_line("finalize helper" & integer'image(x.id));
  end Finalize;

  procedure dummy(x : in out Helper_Type) is
  begin
    ada.text_io.put_line("process Helper" & integer'image(x.id));
  end dummy;

  procedure Finalize(x : in out A) is
  begin
    ada.text_io.put_line("finalize A");
    dummy(Helper);
  end Finalize;

end testff1;

with ada.exceptions;
with ada.text_io;
with testff1;
procedure testff is
  My_A : testff1.A;
begin
  ada.text_io.put_line("main");
exception
  when oops:others=>ada.text_io.put_line(ada.exceptions.exception_information(oops));
end testff;



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

* Re: debugging tool?
  2004-02-21  5:56 debugging tool? tmoran
@ 2004-02-22 21:25 ` Hyman Rosen
  2004-02-22 22:17   ` tmoran
  0 siblings, 1 reply; 9+ messages in thread
From: Hyman Rosen @ 2004-02-22 21:25 UTC (permalink / raw)


tmoran@acm.org wrote:
> Is there a tool around that would scan a large program to check for
> instances of an object being accessed *after* it's been Finalized?

Remember that Ada permits itself to finalize an object more than once.
Your best bet might be to stick in an extra flag in the object and have
the methods check the flag.



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

* Re: debugging tool?
  2004-02-22 21:25 ` Hyman Rosen
@ 2004-02-22 22:17   ` tmoran
  2004-02-22 23:18     ` Stephen Leake
  0 siblings, 1 reply; 9+ messages in thread
From: tmoran @ 2004-02-22 22:17 UTC (permalink / raw)


> > Is there a tool around that would scan a large program to check for
> > instances of an object being accessed *after* it's been Finalized?
>
> Remember that Ada permits itself to finalize an object more than once.
  I don't mean multiple Finalize calls - that's easy.  I mean accessing an
object *after* it's been finalized.  For instance:
  Main_Object : Main_Object_Type;      -- Controlled type
  Helper_Object : Helper_Object_Type;  -- also Controlled
  procedure Finalize(X : in out Helper_Object_Type) is ...
  procedure Finalize(X : in out Main_Object_Type) is
  begin
    do something that accesses Helper_Object
    other stuff
  end Finalize;
At program termination things are Finalized in the reverse order of their
creation.  So Helper_Object gets Finalized.  Then Main_Object is Finalized
- but that process includes accessing Helper_Object, which has already
been finalized.  Perhaps it contained pointers that were deallocated so
the attempt to use it *after finalization* crashes.  If Helper_Object is
declared *before* Main_Object, all is well.  I recently ran into something
like this where Helper involved a protected object and an attempt to call
the protected object after it had been finalized was not good.  It seems
to me a fairly easy mistake to declare the helper after the main object,
and it seems like a fairly simple minded source code analysis tool could
detect the problem.



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

* Re: debugging tool?
  2004-02-22 22:17   ` tmoran
@ 2004-02-22 23:18     ` Stephen Leake
  2004-02-23  1:21       ` tmoran
  0 siblings, 1 reply; 9+ messages in thread
From: Stephen Leake @ 2004-02-22 23:18 UTC (permalink / raw)
  To: comp.lang.ada

tmoran@acm.org writes:

> > > Is there a tool around that would scan a large program to check for
> > > instances of an object being accessed *after* it's been Finalized?
> >
> > Remember that Ada permits itself to finalize an object more than once.
>   I don't mean multiple Finalize calls - that's easy.  I mean accessing an
> object *after* it's been finalized.  

Right. So put in a flag Object.Finalized, and check Object.Finalized
in _every_ operation on Object. Raise an exception, or silently do
nothing, your choice.

-- 
-- Stephe




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

* Re: debugging tool?
  2004-02-22 23:18     ` Stephen Leake
@ 2004-02-23  1:21       ` tmoran
  2004-02-23  1:31         ` tmoran
  2004-02-23  3:34         ` Stephen Leake
  0 siblings, 2 replies; 9+ messages in thread
From: tmoran @ 2004-02-23  1:21 UTC (permalink / raw)


> Right. So put in a flag Object.Finalized, and check Object.Finalized
> in _every_ operation on Object. Raise an exception, or silently do
> nothing, your choice.
> >   Main_Object : Main_Object_Type;      -- Controlled type
> >   Helper_Object : Helper_Object_Type;  -- also Controlled
By "Object" here you must mean Main_Object_Type, right?  So
  type Main_Object_Type is new Ada.Finalization.Controlled with record
    Helper_Finalized : Boolean
    ...
That's great for future development, but I'm look for something to
automatically examine a large body of existing code.  Often
Main_Object_Type doesn't know much at all about Helper_Object_Type, and
may well have been coded long before someone added a helper type.  (eg,
Helper_Type keeps a usage count of Main_Object_Type's and does something
when they've all gone away.  Even if Helper_Type is a simple integer, it's
questionable to access it after it's de-elaborated=finalized).
In general, I'd like a tool (if not the compiler) to catch non-obvious
errors like this.



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

* Re: debugging tool?
  2004-02-23  1:21       ` tmoran
@ 2004-02-23  1:31         ` tmoran
  2004-02-23  3:54           ` Stephen Leake
  2004-02-23  3:34         ` Stephen Leake
  1 sibling, 1 reply; 9+ messages in thread
From: tmoran @ 2004-02-23  1:31 UTC (permalink / raw)


> Right. So put in a flag Object.Finalized, and check Object.Finalized
Oops, I knew I needed a cup of coffee.  Clearly that flag can't go in
Main_Object_Type because there is, in general, no way Finalize(Helper)
could know about all the Main_Object_Type's around and set their flags.
And it can't go in Helper_Object_Type unless you are willing to check
it by accessing Helper from Finalize(Main_Object_Type) after Helper has
been finalized.  So maybe the question becomes:  is it safe to access
simple things like booleans after they've been finalized/de-elaborated?



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

* Re: debugging tool?
  2004-02-23  1:21       ` tmoran
  2004-02-23  1:31         ` tmoran
@ 2004-02-23  3:34         ` Stephen Leake
  1 sibling, 0 replies; 9+ messages in thread
From: Stephen Leake @ 2004-02-23  3:34 UTC (permalink / raw)
  To: comp.lang.ada

tmoran@acm.org writes:

> > Right. So put in a flag Object.Finalized, and check Object.Finalized
> > in _every_ operation on Object. Raise an exception, or silently do
> > nothing, your choice.
> > >   Main_Object : Main_Object_Type;      -- Controlled type
> > >   Helper_Object : Helper_Object_Type;  -- also Controlled
> By "Object" here you must mean Main_Object_Type, right?  So
>   type Main_Object_Type is new Ada.Finalization.Controlled with record
>     Helper_Finalized : Boolean
>     ...

No, the flag has to go in helper_type; it's the one being finalized
and then accessed.

> That's great for future development, but I'm look for something to
> automatically examine a large body of existing code. 

Ok, if you can't change the code, you have a problem :).

But I'm suggesting you only have to change Helper_Type and the
operations on Helper_Type, not everything that uses Helper_Type. Does
that make it easier to do?

> Often Main_Object_Type doesn't know much at all about
> Helper_Object_Type, and may well have been coded long before someone
> added a helper type. (eg, Helper_Type keeps a usage count of
> Main_Object_Type's and does something when they've all gone away.
> Even if Helper_Type is a simple integer, it's questionable to access
> it after it's de-elaborated=finalized).

Hmm. If Helper_Object truly de-elaborated, that means it's gone out of
scope. So if Main_Object is still "accessing" it, it must be thru a
"dangling pointer". So you need a pointer tracker tool.

If Helper_Object is still in scope, any access to it can check a flag
in Helper_Object first.

I've added such a flag to your original example:

with ada.finalization;
package testff1 is
  type A is new ada.finalization.controlled with null record;
  procedure Finalize(x : in out A);
  AA : A;
private
   type Helper_Type(id : integer) is new ada.finalization.controlled with record
     Finalized : Boolean := False;
   end  record;
  procedure Finalize(x : in out Helper_Type);
  procedure dummy(x : in out Helper_Type);
end testff1;

with ada.text_io;
package body testff1 is

  Helper : Helper_Type(1);

  procedure Finalize(x : in out Helper_Type) is
  begin
     ada.text_io.put_line("finalize helper" & integer'image(x.id));
     X.Finalized := True;
  end Finalize;

  procedure dummy(x : in out Helper_Type) is
  begin
     if X.Finalized then
        Ada.Text_IO.Put_Line ("attempt to process finalized helper");
     else
        ada.text_io.put_line("process Helper" & integer'image(x.id));
     end if;
  end dummy;

  procedure Finalize(x : in out A) is
  begin
    ada.text_io.put_line("finalize A");
    dummy(Helper);
  end Finalize;

end testff1;

./testff.exe 
main
finalize A
process Helper 1
finalize helper 1
finalize A
attempt to process finalized helper

> In general, I'd like a tool (if not the compiler) to catch
> non-obvious errors like this.

That would require full data flow analysis. Better to redesign to
avoid such problems in the first place.

-- 
-- Stephe




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

* Re: debugging tool?
  2004-02-23  1:31         ` tmoran
@ 2004-02-23  3:54           ` Stephen Leake
  2004-02-23  5:43             ` tmoran
  0 siblings, 1 reply; 9+ messages in thread
From: Stephen Leake @ 2004-02-23  3:54 UTC (permalink / raw)
  To: comp.lang.ada

tmoran@acm.org writes:

> So maybe the question becomes:  is it safe to access
> simple things like booleans after they've been finalized/de-elaborated?

That depends on why Finalize got run. If it was in response to a call
to Unchecked_Deallocation, and the memory really was deallocated, then
it is not safe. But then you have a dangling pointer problem, for
which there are tools. 

Hmm. In your example, Helper_Object was declared in a package body,
and Main_Object in the main program. The compiler decided to finalize
objects in the package body before objects in the main program. 

Hmm. ARM 7.6.1 says the objects declared in the main program
should have been finalized before objects declared in packages. So
this looks like a compiler bug.

However, Annotated ARM 7.6.1 11.g says:

          Implementation Note: An implementation has to ensure that the
          storage for an object is not reclaimed when references to the
          object are still possible (unless, of course, the user
          explicitly requests reclamation via an instance of
          Unchecked_Deallocation). This implies, in general, that
          objects cannot be deallocated one by one as they are
          finalized; a subsequent finalization might reference an
          object that has been finalized, and that object had better be
          in its (well-defined) finalized state.

That says it is safe to put a Finalized flag in Helper_Type, as long
as you are not using Unchecked_Deallocation.

-- 
-- Stephe




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

* Re: debugging tool?
  2004-02-23  3:54           ` Stephen Leake
@ 2004-02-23  5:43             ` tmoran
  0 siblings, 0 replies; 9+ messages in thread
From: tmoran @ 2004-02-23  5:43 UTC (permalink / raw)


> However, Annotated ARM 7.6.1 11.g says:
> ...
>           objects cannot be deallocated one by one as they are
>           finalized; a subsequent finalization might reference an
>           object that has been finalized, and that object had better be
>           in its (well-defined) finalized state.
>
> That says it is safe to put a Finalized flag in Helper_Type, as long
> as you are not using Unchecked_Deallocation.
   Excellent!  Thanks.



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

end of thread, other threads:[~2004-02-23  5:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-02-21  5:56 debugging tool? tmoran
2004-02-22 21:25 ` Hyman Rosen
2004-02-22 22:17   ` tmoran
2004-02-22 23:18     ` Stephen Leake
2004-02-23  1:21       ` tmoran
2004-02-23  1:31         ` tmoran
2004-02-23  3:54           ` Stephen Leake
2004-02-23  5:43             ` tmoran
2004-02-23  3:34         ` Stephen Leake

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