06301326.txt 30-Jun-00


GC Call Failure

Hi,

Can anybody explain why the code below sometimes fails,
  causing a GPF of sorts?
  IF !InCollect()
    Collect()
  ENDIF
I used to have CollectForced() instead of Collect() but I
  got even more errors. I want to use this in a Close()
  method of a window class in order to force cleanups that
  sometimes would not happen when I need them to. It doesn't
  fail all the time, just randomly. My understanding was
  that InCollect() was supposed to protect the GC call if it
  was already in operation.

Thanks.
Geoff


Hi Geoff,

Are you calling this in a .dll loaded by
  LoadLibrary/_VOLoadLibrary, later on call this again in
  the startup .exe?
I have experience some problem that will not happen when I
  use _DLL way.

Regards,
Wong


Hi Wong,

No, its just in the main exe.

Geoff


Geoff,

We need to see all of the code around this so that we can
  see exactly the context under which this is happening. <g>
Seriously, if this code is being called from within a close
  method, what one of my observations has been is that that
  code doesn't always get called when you expect it.
  Consequently the reference to the window might be already
  out of scope?
Just a thought ...


Gary,

This is the code, the whole code and nothing but the code
  <g>:
METHOD Close (oEvent) CLASS MyDataListingWindow
  // Call Async API sound effect
  MakeSound("CloseScreen.wav")

  // remove timer object
  KillTimer(SELF:Handle(0), TIME_EVENT_6)
  IF IsMethod(SELF:Owner, #DeleteChildWindow)
    SELF:Owner:DeleteChildWindow( SELF )
  ENDIF
  SUPER:Close(oEvent)
  IF !InCollect()
    CollectForced()
  ENDIF
RETURN TRUE
Ovbiously the original idea was to tidy up after myself.
  These are windows which have components generated at
  runtime so I can never be sure what might be left after it
  closes. I took the sound call out - no difference.
DeleteChildWindow() on the owner shouldn't be an issue as
  its the same as used in the SSA tutorial. The error
  usually happens on the InCollect() line??? which I thought
  was nothing more than a test that should not even be
  necessary under the circumstances
Would this be better placed in the Axit() method maybe? Or
  even Destroy().

Geoff


Geoff,

Try it in the WM_CLOSE message of the Dispatch().
Another thing.  Are you sure it's caused by the code you
  posted ?  It might be something else that's been lurking
  in memory at the moment you instantiated the Window.

Stephane Hebert


No I am not sure.
I'll give your suggestion a try. Thanks.

Geoff


Hi Geoff,

We donnot have VO SDK, so this just a guess:
If I'm the disigner of VO GUI class, to work with GC, I will
  put a call to RegisterKid() in VObject:Init(), and
  UnregisterKid() in VObject:Destroy().
In Window:Close(), I will call Window:Destroy(), and in
  Window:Destroy(), I will call SUPER:Destroy(), and the end
  result is, VObject:Destroy() will be called, and
  UnregisterKid() have remove the entry of this object from
  the table.
What I try to say is, we should not put any code after
  VObject:Destroy().
And what are  SELF:Owner:DeleteChildWindow( SELF ) doing?
  Are it simply remove the reference of SELF from an array
  kept by Owner, or it also call SELF:Close()?
Anyway, try to move IF !InCollect() before
  SUPER:Close(oEvent), and see it's the problem solved. If
  not, move IF !InCollect() before  IF IsMethod(SELF:Owner,

  #DeleteChildWindow) and try again.
Sorry, I have difficulty to express what I'm thinking. I
  hope you understand what I try to say. :-)

HTH,
Wong


Hi Wong,

>
... call SUPER:Destroy(), and the end result is,
  VObject:Destroy() will be called, and UnregisterKid() have
  remove the entry of this object from the table. What I try
  to say is, we should not put any code after
  VObject:Destroy().
<
But this is where I would expect to put garbage collection
  calls - after everything has been deleted. All the other
  calls you mention are right where you say they are - its
  native VO code anyway.
>
And what are  SELF:Owner:DeleteChildWindow( SELF ) doing?
  Are it simply remove the reference of SELF from an array
  kept by Owner, or it also call SELF:Close()?
<
Yes, this is an array in the shell window class that
  maintains an array of all child windows. When a child
  window closes, it deletes itself from the array. It does
  nothing else. I took this from the SSA Tutorial (but I
  don't even use the array - aren't we slaves to habit <g>).
>
Anyway, try to move IF !InCollect() before
  SUPER:Close(oEvent), and see it's the problem solved. If
  not, move IF !InCollect() before  IF IsMethod(SELF:Owner,
  #DeleteChildWindow) and try again.
<
I have tried this. In fact I moved to after the
  Super:Close() when it first gave me trouble. Funny thing
  is, I have had that code in there for a year but it has
  only given me trouble since 2.5a - I'm not making any
  conclusion here on 2.5a because I have also mad other
  substantial changes to my app.
>
Sorry, I have difficulty to express what I'm thinking. I
  hope you understand what I try to say. :-)
<
Yep! You're doing just fine <g>.

Thanks for the thoughts.
Geoff


I guess the problem is somewhere else and not in this piece
  of code.
But: when closing window call EndWindow(TRUE) instead of
  EndWindow(). If flag is set to TRUE it should send message
  to that window instead of posting it. It should give
  windows some chance to breath.
It's just an idea....


Greetings from
Pavel Vetesnik


Hi Pavel,

I have tried this before and got into serious difficulties.
  There seem to be ocassions when this is good and times
  when it crashes the computer. I use the ESCAPE key to
  close windows from the dispatch. If I use TRUE there, its
  a disaster. If I just EndWindow(TRUE) from a method, its
  usually OK but TRUE will fail every time if I have that
  offending piece of code in the Close() <g>. The only thing
  happening with TRUE is that the WM_CLOSE message is sent
  with SEND and not just POST - so what else is left in the
  message queue to upset things?
There are some mysteries here that do not want to be solved.
  And why InCollect() should be the point of failure is the
  biggest mystery.

Geoff


Hi,

I *think* you have the same sort of problems like 4660/5333
  errors, so you should use the same techniques which where
  described for such reasons (observing
  memory(MEMORY_REGISTERAXIT), etc...).

HTH (a bit)
Pavel


Some thoughts,

Destroy is called automatically after Close (check
  window:dispatch and window:__close) so you don't have to
  call the garbage collector to make this happen.
I don't know why InCollect generates an error, but you can
  always insert a _dyncheck to see if dynamic memory is
  corrupted.

Mathias


Thankyou for the thoughts.
_Dyncheck() revealed nothing.
What I was trying to do was force a cleanup. I have a screen
  view of some high resolution graphics (ie screen view
  before printing). Because I can let the user zoom and
  scroll, it was eating enormous amounts of resources and
  did sometimes crash the user's box. The answer was to
  force garbage collection. Each time I closed the screen,
  all the registered axits and dynamic memory satyed
  allocated until the GC chose when it wanted to work.
Unfortunately, some users went back into this resource-
  intensive routine and just blew up RAM. I found that my
  only way out was to deliberately invoke the GC and then

  this stablised everything. The Close() was simply a
  guaranteed point and seemed not to interfere with the
  existing destruction sequence. But the consequence was an
  occassional failure on InCollect().
I am not the only person to experience failures on
  InCollect().

geoff


Why can't you make your own destroy method in your window
  that deallocates the recources that your code has
  allocated? This should clear up the memory for you. This
  problem will probably very hard to analyze so the best
  thing for you is probably to try to move your code
  somewhere else and see if it works better.
It's really like physics. There's often no way to directly
  understand and analyze the laws of nature. All we can do
  is silly experiments and see what happens. (Does it hurt
  when I touch these wires at the same time?). The only
  difference is that once in a while God speaks to us, and
  sometimes he (yes girls, in this case it's a male)
  reaveals something new.

Mathias


You are probably right, experimentation..... <sigh>.
So I think this problem is a female one. Changes its mind
  all the time, expensive to look after and hard to find
  <bg>. But when you finally catch up with it, it was worth
  all that trouble!


Hello Mathias

Yes, I really do think you're right!
But even the GC has some kind of logic, it just so very well
  hidden down there in the inner secrets of Windows memory
  handling <g>.
Who has really written the VO GC? Or have they bought it
  without the source code, just like the ... databrowser?
  (Gunnar Bless, couldn't you just take a look into this
  logic, too?)

Olav


Olav,

All in all, I am certain that the GC is a purely Dev Team
  thing. And to be fair, it is one feature which sets VO
  above C++ (although it is obviously written in C <g>) and
  many other languages. As it automates so much memory
  management for us, I can live with its shortcomings.
Judging by the number of questions I have seen asked here,
  on Compuserve and at technical conferences and judging by
  the almost total lack of CA response, I suspect that it is
  the baby of just one or two on the dev team (possibly the
  original authors left the team and others have taken it

  over) and that it is such a complex beast internally that
  they find it difficult to explain. I have seen a number of
  papers recently in SDT and other places on the GC but they
  don't really explain its mechanics. Just how to work
  around issues with dynamic memory. Uwe Holz's article in
  Issue 3/99 of SDT is mandatory reading but he does not
  explain how it is called, what InCollect() and Collect()
  are doing, what watermarks are and how they are
  determined, the relationship with RegisterKid() etc, etc,
  etc.
Lets just keep the pressure up to prise out as many
  "secrets" as we can <g>.

Geoff


Geoff,

My guess is that you are calling InCollect() at a "Bad"
  time; that is just when the GC is about to be invoked.
  Obviously that should not cause the error anyway but since
  it does, perhaps the safest way is to set a GC Timer that
  is called lets say 1 sec. after any window closes. Should
  just take a couple of minutes to set up. At that point the
  system should be more "stable".

Nathan


Hi Nathan,

In fact, I did just what you said. In my shell window I set
  up a timer to fire off evey 5 sec. This then calls the GC
  and evokes any and all tidy ups.
Hence I removed the lines from the close method. The trouble
  is that this does not help me find WHERE I am causing any
  problem.
But it still does not explain what's wrong. And as you said,
  I thought InCollect() was meant to determine this.
The mystery remains.

Geoff


Hi Geoff

I have read, i don't remeber where, that in VO 2.5x, the
  function 'CollectForced' call internally the function
  'InCollect', I am not sure if this is true o false.

Jesus


You are right - I remember that too. Back at Technicon it
  was one of the "fixes" Sabo announced to everyone. But
  since then I could not find any reference to this in any
  documentation with 2.5 so I forgot about it. Even the
  current SDK uses this in its destroy methods right now -
  but I am sure you are right. This beggars further
  investigation.


Geoff


Geoff,

A couple of workarounds you might consider if the problem
  continues.
Try moving the Collectforced() code in front of the startup
  code of the window, instead of the close of the window.
If still no answer.   How about putting the graphics display
  piece in its own EXE.  When they close it, it closes the
  EXE, and memory should not be a concern.

Good luck,
Paul Bartlett


Paul,

I follow what you mean but the graphics are integral to the
  app - I couldn't even put it in another thread.  But as
  the others suggested, I will just have to play around with
  its location: its all about real estate - location,
  location, location<g>.

Geoff