Page 1 of 1

Properly method to destroy objects

PostPosted: Wed Oct 11, 2006 3:34 pm
by pawelu
Antonio,

What is properly method to destroy objects in window. I create window with several controls eg. listbox, say, get. When this window is loaded several times memory is not freed after window End() procedure. This generally provide to Internal Error without error description (ca up to 85% load memory use). I try assign object to control and End() or Destroy() method use but no success. Memory usage grow after load window.

Thanks
Pawel

PostPosted: Wed Oct 11, 2006 3:46 pm
by Antonio Linares
Pawel,

What FWPPC build (date) are you using ?

PostPosted: Wed Oct 11, 2006 4:26 pm
by pawelu
Antonio,

I use FWPPC 08/September/2006 build.
In EVC Rempte System Information memory usage like this:
program load: 37%
second window with 36 get control load 20 times: 42%
program crash when momory usage is ca 85%

Pawel

PostPosted: Wed Oct 11, 2006 8:54 pm
by Antonio Linares
Pawel,

Please download a more recent FWPPC build, thanks.

PostPosted: Thu Oct 12, 2006 3:40 pm
by pawelu
Antonio,

This is memory log and test procedure for test with new FWPPC build. It's look like nothing is change.

Regards
Pawel

Memory before: 40,464,384
1 call, before: 40,259,584 after: 39,862,272
2 call, before: 39,862,272 after: 39,727,104
3 call, before: 39,727,104 after: 39,575,552
4 call, before: 39,575,552 after: 39,436,288
5 call, before: 39,436,288 after: 39,284,736
6 call, before: 39,284,736 after: 39,124,992
7 call, before: 39,124,992 after: 38,985,728
8 call, before: 38,985,728 after: 38,825,984
9 call, before: 38,825,984 after: 38,678,528
10 call, before: 38,678,528 after: 38,522,880
11 call, before: 38,522,880 after: 38,375,424
12 call, before: 38,375,424 after: 38,227,968
13 call, before: 38,227,968 after: 38,076,416
14 call, before: 38,076,416 after: 37,916,672
15 call, before: 37,916,672 after: 37,773,312
16 call, before: 37,773,312 after: 37,613,568
17 call, before: 37,613,568 after: 37,474,304
18 call, before: 37,474,304 after: 37,318,656
19 call, before: 37,318,656 after: 37,163,008
20 call, before: 37,163,008 after: 37,027,840
Memory after: 37,027,840
Memory lost: 3,436,544

test procedure:
Code: Select all  Expand view
#Include 'FwCe.Ch'

#Define CRLF Chr (13) + Chr (10)

Function TestMem ()

   Local oWnd := Nil
   Local nHn := 0
   Local i := 0
   Local j := 0
   Local k := 0
   Local aMem := {0, 0}

   nHn := FCreate ('MEM.INFO')
   FWrite (nHn, 'Memory before:' + TransForm (j := MemInfo (), '999,999,999') + CRLF)

   Define Window oWnd Title 'Test Memory'
   @ 226, 176 Button 'Ok' Size 60, 20 Pixel Action (aMem[1] := MemInfo (), NextWnd (++ i), aMem[2] := MemInfo (), MemStatus (nHn, i, aMem))
   Activate Window oWnd

   FWrite (nHn, ' Memory after:' + TransForm (k := MemInfo (), '999,999,999') + CRLF)
   FWrite (nHn, '  Memory lost:' + TransForm (j - k, '999,999,999') + CRLF)
   FClose (nHn)

Return .T.

Function NextWnd (nCnt)

   Local oWnd := Nil
   Local cGet := Space (20)

   Define Window oWnd Title 'Next Window'
   @  24,  5 Get cGet Size 50, 20 Pixel
   @  24, 60 Get cGet Size 50, 20 Pixel
   @  24,120 Get cGet Size 50, 20 Pixel
   @  24,180 Get cGet Size 50, 20 Pixel
   @  46,  5 Get cGet Size 50, 20 Pixel
   @  46, 60 Get cGet Size 50, 20 Pixel
   @  46,120 Get cGet Size 50, 20 Pixel
   @  46,180 Get cGet Size 50, 20 Pixel
   @  68,  5 Get cGet Size 50, 20 Pixel
   @  68, 60 Get cGet Size 50, 20 Pixel
   @  68,120 Get cGet Size 50, 20 Pixel
   @  68,180 Get cGet Size 50, 20 Pixel
   @  90,  5 Get cGet Size 50, 20 Pixel
   @  90, 60 Get cGet Size 50, 20 Pixel
   @  90,120 Get cGet Size 50, 20 Pixel
   @  90,180 Get cGet Size 50, 20 Pixel
   @ 112,  5 Get cGet Size 50, 20 Pixel
   @ 112, 60 Get cGet Size 50, 20 Pixel
   @ 112,120 Get cGet Size 50, 20 Pixel
   @ 112,180 Get cGet Size 50, 20 Pixel
   @ 134,  5 Get cGet Size 50, 20 Pixel
   @ 134, 60 Get cGet Size 50, 20 Pixel
   @ 134,120 Get cGet Size 50, 20 Pixel
   @ 134,180 Get cGet Size 50, 20 Pixel
   @ 156,  5 Get cGet Size 50, 20 Pixel
   @ 156, 60 Get cGet Size 50, 20 Pixel
   @ 156,120 Get cGet Size 50, 20 Pixel
   @ 156,180 Get cGet Size 50, 20 Pixel
   @ 178,  5 Get cGet Size 50, 20 Pixel
   @ 178, 60 Get cGet Size 50, 20 Pixel
   @ 178,120 Get cGet Size 50, 20 Pixel
   @ 178,180 Get cGet Size 50, 20 Pixel
   @ 200,  5 Get cGet Size 50, 20 Pixel
   @ 200, 60 Get cGet Size 50, 20 Pixel
   @ 200,120 Get cGet Size 50, 20 Pixel
   @ 200,180 Get cGet Size 50, 20 Pixel
   @ 222,  0 Say 'Window:' + PadL (nCnt, 3) Size 150, 15 Pixel
   @ 246, 176 Button 'Close' Size 60, 20 Pixel Action oWnd : End ()
   Activate Window oWnd

Return .T.

Function MemStatus (nHn, nCnt, aMem)

   FWrite (nHn, PadL (nCnt, 2) + ' call, before:' + TransForm (aMem[1], '999,999,999') + ' after:' + TransForm (aMem[2], '999,999,999') + CRLF)

Return .T.

#pragma BEGINDUMP

#include <hbapi.h>
#include <windows.h>
#include <aygshell.h>

HB_FUNC (MEMINFO)
{
   MEMORYSTATUS st;
   GlobalMemoryStatus (&st);

   hb_retnl ((ULONG) st.dwAvailPhys);
}

#pragma ENDDUMP

PostPosted: Thu Oct 12, 2006 11:25 pm
by Antonio Linares
Pawel,

We are doing some tests with your sample code, thanks.

PostPosted: Fri Oct 13, 2006 1:00 am
by Antonio Linares
Pawel,

Place a call to hb_gcAll() after closing the second window:
Code: Select all  Expand view
   @ 222,  0 Say 'Window:' + PadL (nCnt, 3) Size 150, 15 Pixel
   @ 246, 176 Button 'Close' Size 60, 20 Pixel Action oWnd : End ()
   Activate Window oWnd
   
   hb_gcAll()

hb_gcAll() invokes the Harbour garbage collector. Anyhow, we keep doing more tests.

PostPosted: Fri Oct 13, 2006 9:38 am
by Antonio Linares
Pawel,

This sample starts having a memory leak when you click on the button for 20 times or so. We are trying to locate which method is consuming the memory:
Code: Select all  Expand view
#include "FWCE.ch"

static oWnd, oSay, nStart

function Main()

   nStart = MemInfo()

   DEFINE WINDOW oWnd TITLE "MemTest"

   @ 11,  2 SAY oSay PROMPT "Diff: " + Transform( 0, "999,999,999" ) SIZE 150, 20

   @ 13, 13 BUTTON "Go" SIZE 70, 22 ACTION Test()

   ACTIVATE WINDOW oWnd

return nil

function Test()

   local cTest := Space( 10 ), n

   /*
   @ 2,  3 GET cTest SIZE 80, 20
   @ 2, 16 GET cTest SIZE 80, 20
   @ 4,  3 GET cTest SIZE 80, 20
   @ 4, 16 GET cTest SIZE 80, 20
   @ 6,  3 GET cTest SIZE 80, 20
   @ 6, 16 GET cTest SIZE 80, 20
   */

   // @ 2, 2 BUTTON "Test" SIZE 80, 20
   TButtonX():New( 2, 2, "Test",,, 80, 20 )
   TButtonX():New( 4, 2, "Another",,, 80, 20 )

   for n = 3 to Len( oWnd:aControls )
      oWnd:aControls[ n ]:End()
   next   

   hb_gcAll()

   oSay:SetText( "Diff: " + Transform( nStart - MemInfo(), "999,999,999" ) )   
   nStart = MemInfo()
   
return nil   

CLASS TButtonX FROM TButton

   CLASSDATA lRegistered
   
   // METHOD New() INLINE ::Create( "BUTTON" )
   METHOD Initiate() INLINE MsgInfo( "Initiate" )
   METHOD Colors() VIRTUAL
   METHOD GetFont() VIRTUAL
   METHOD HandleEvent() VIRTUAL
   METHOD SetFont() VIRTUAL
   METHOD Register() VIRTUAL
   METHOD Create() VIRTUAL
   METHOD Link() VIRTUAL
   
ENDCLASS   

#pragma BEGINDUMP

#include <hbapi.h>
#include <windows.h>
#include <aygshell.h>

HB_FUNC( MEMINFO )
{
   MEMORYSTATUS st;
   GlobalMemoryStatus( &st );

   hb_retnl( ( ULONG ) st.dwAvailPhys );
}

#pragma ENDDUMP

PostPosted: Fri Oct 13, 2006 12:39 pm
by Antonio Linares
Pawel,

Lets check all the static variables of the application with array type, to see if one of them is growing on each call:
Code: Select all  Expand view
static aStatSizes
...
   local n, aSizes

   if aStatSizes == Nil
      aStatSizes = Array( HB_DBG_VMVARSLEN() )
      for n = 1 to HB_DBG_VMVARSLEN()
         if ValType( HB_DBG_VMVARSGET( n ) ) == "A"
            aStatSizes[ n ] = Len( HB_DBG_VMVARSGET( n ) )
         endif
      next       
   else
      for n = 1 to HB_DBG_VMVARSLEN()
         if ValType( HB_DBG_VMVARSGET( n ) ) == "A"
            if aStatSizes[ n ] != Len( HB_DBG_VMVARSGET( n ) )
               MsgInfo( "Static " + Str( n ) + " has grown!" )
            endif   
         endif
      next       
      aSizes = Array( HB_DBG_VMVARSLEN() )
      for n = 1 to HB_DBG_VMVARSLEN()
         if ValType( HB_DBG_VMVARSGET( n ) ) == "A"
            aSizes[ n ] = Len( HB_DBG_VMVARSGET( n ) )
         endif
      next       
      aStatSizes = aSizes
   endif