Página 1 de 4

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 05 Set 2022 16:14
por carlaoonline
Boa tarde!

Estou com um problema de não conseguir liberar memória após dar um release em um formulário com objeto TBrowse dentro.

Ao fechar o Form, sigo essa ordem:

Código: Selecionar todos

oBrw:Destroy()  // Destruo o Objeto Tbrowse
DoMethod(cForm,cControl,"Release")  // Apago o controle TBrowse 
DoMethod(cForm,"Release")    // Apago o Formulario criado
Form_Main.SetFocus()  // Volto para o principal
Porém a memória não libera.

Fiz um código teste abaixo, que a cada clicada no botão cria um novo formulário com um objeto TBrowse de 500.000 elementos com nome diferente e ao dar ESC "deveria liberar a memória" mas não está acontecendo...

Se alguém puder me dar uma luz eu agradeço!

Código: Selecionar todos

#include "minigui.ch"
#include "TSBrowse.ch"

PROCEDURE MAIN

Public aHeaders:={"Ordem","Nome_cli","Data","Marcado","Endereco","REG_"}
Public MemoriaInicial:=Alltrim(str(Memory(0)))
DEFINE WINDOW Form_Main;
   TITLE "Janela prncipal" MAIN ;
   ON GOTFOCUS Atualiza_botao() 
   @ 175,620 button btn01 caption "Gerar TBrowse  -  (Memoria Inicial = "+MemoriaInicial +")" Width 480 Height 50 action CreateTBrowse(Memory(0))
END WINDOW

ON KEY ESCAPE of Form_Main ACTION Form_Main.Release
ACTIVATE WINDOW Form_Main

RETURN


//---------------------------------------------------------
FUNCTION CreateTBrowse(nMemoria)
//---------------------------------------------------------
Local F ,ARQ_TEMP:=ARQ_TEMPORARIO()
Local cForm:="FORM_"+ALLTRIM(SUBST(ARQ_TEMP,3,10))
Local oBrw:="oBrw_"+ALLTRIM(SUBST(ARQ_TEMP,3,10))
Private aLista:={}


WAIT WINDOW "Adicionando elementos em aLista{}. Aguarde..." NOWAIT
FOR F := 1 TO 500000 
    AAdd( aLista, { F, Hb_RandomInt(99) , RandStr( 10 ), Date() - F, if( F % 2 == 0, TRUE, FALSE ), RandStr( 10 ), F*10   } )
NEXT
WAIT CLEAR

DECLARE WINDOW &(cForm) 

DEFINE WINDOW &cForm width 600 height 480 TITLE "--- >>> DE UM DUPLO CLICK EM QUALQUER CELULA " ;
       ON INIT Atualiza_Botao();
       ON RELEASE Atualiza_Botao()

       @ 15, 20 LABEL Lbl_Memoria FontColor RED WIDTH 450  HEIGHT 23 ;
       VALUE "Memoria Antes de criar o TBrowse = "+Alltrim(str(nMemoria)+"    Apos = ") 


END WINDOW



DEFINE TBROWSE &oBrw OBJ &(oBrw) ;
       AT 45, 2 ;
       OF &cForm ;
       WIDTH 590 ;
       HEIGHT 470;
       ON DBLCLICK ( Atualiza_Botao() , PrimeiraFuncao(cForm, &(oBrw), oBrw ) );  // ( Formulario , Objeto Tbrowse , Controle TBrowse )
       ON CHANGE Atualiza_Botao();
       HEADERS aHeaders ;
       GRID
END TBROWSE

ON KEY ESCAPE OF &cForm ACTION FechaForm( cForm, &(oBrw), oBrw  )  // ( Formulario , Objeto Tbrowse , Controle TBrowse )

&oBrw:SetArray( aLista, .T. )
&oBrw:Cargo:=aLista

SetProperty(cForm,"Lbl_Memoria","Value",GetProperty(cForm,"Lbl_Memoria","Value")+Alltrim(Str(memory(0))))

ACTIVATE WINDOW &cForm
RETURN oBrw
//---------------------------------------------------------


//---------------------------------------------------------
Function Atualiza_Botao()
//---------------------------------------------------------
SetProperty("Form_Main","btn01","caption","Gerar TBrowse    ( Memoria Inicial = "+MemoriaINicial+"    Memoria Atual = "+alltrim(str(memory(0)))+" )") 
Return NIL
//---------------------------------------------------------

//---------------------------------------------------------
FUNCTION PrimeiraFuncao(cForm, oBrw, cControl)  // ( Formulario , Objeto Tbrowse , Controle TBrowse )
//---------------------------------------------------------
Local cQtdElementos,aNewArray01, m1, m2, nLinha, nColuna

m1=alltrim(str(memory(0)))  // Antes de atribuir a matriz aLista (que esta em oBrw:cargo) para a aNewArray01
aNewArray01=oBrw:cargo
m2=alltrim(str(memory(0)))  // Apos criar a aNewArray01 com o valor de oBrw:cargo

cQtdElementos=Len(aNewArray01)
nLinha=oBrw:nAt
nColuna=oBrw:nCell
// Valor=Alltrim(Hb_ValToStr(GetProperty(cForm,cControl,"value")))
Valor=Hb_ValToStr(aNewArray01[nLinha][nColuna])
msgbox("DENTRO da PrimeiraFuncao()"+Hb_Eol()+ Hb_Eol()+;
       "Array inicial aLista com 1000000 elementos atribuida => 'oBrw:cargo:=aLista'"+ Hb_Eol()+ Hb_Eol()+;
       "Memoria antes de 'aNewArray01=oBrw:cargo' = "+ M1 + Hb_Eol()+;
       "Quantidade de elementos de aNewArray01 = "+alltrim(str(cQtdElementos))+Hb_Eol()+;
       "Memoria  apos  'aNewArray01=oBrw:cargo' = "+ M2 + Hb_Eol()+;
       "Celula clicada:   Linha="+alltrim(str(nLinha))+"   Coluna="+alltrim(str(nColuna))+ "    Valor="+Valor )

SegundaMensagem(cForm, oBrw, cControl, m1, m2)

Return NIL
//---------------------------------------------------------

//---------------------------------------------------------
Function SegundaMensagem(cForm, oBrw, cControl, m1, m2)
//---------------------------------------------------------
Local cQtdElementos,aNewArray02, m3, m4, nLinha, nColuna

m3=alltrim(str(memory(0)))  // Antes de atribuir a matriz aLista (que esta em oBrw:cargo) para a aNewArray02
aNewArray02=oBrw:cargo
m4=alltrim(str(memory(0)))  // Apos criar a aNewArray02 com o valor de oBrw:cargo

cQtdElementos=Len(aNewArray02)
nLinha=oBrw:nAt
nColuna=oBrw:nCell
// Valor=Alltrim(Hb_ValToStr(GetProperty(cForm,cControl,"value")))
Valor=Hb_ValToStr(aNewArray02[nLinha][nColuna])

msgbox("DENTRO da SegundaFuncao:"+Hb_Eol()+ Hb_Eol()+;
       "Memoria antes de 'aNewArray02=oBrw:cargo' = "+ m3 + Hb_Eol()+;
       "Na PrimeiraFuncao era ="+M1 + Hb_Eol()+;
       "Quantidade de elementos de aNewArray02 = "+alltrim(str(cQtdElementos))+Hb_Eol()+;
       "Memoria  apos   'aNewArray02=oBrw:cargo' = "+ M4 + Hb_Eol()+;
       "Na PrimeiraFuncao era ="+M2 + Hb_Eol()+;
       "Celula clicada:   Linha="+alltrim(str(nLinha))+"   Coluna="+alltrim(str(nColuna))+ "    Valor="+Valor )
Return Nil
//---------------------------------------------------------




//---------------------------------------------------------
FUNCTION FechaForm(cForm, oBrw, cControl  )  // ( Formulario , Objeto Tbrowse , Controle TBrowse )
//---------------------------------------------------------
m1=alltrim(str(memory(0)))
oBrw:Destroy()
m2=alltrim(str(memory(0)))

DoMethod(cForm,cControl,"Release")

msgbox("Memoria antes do oBrw:Destroy()="+m1+ Hb_Eol()+;
       "Memoria apos o oBrw:Destroy()="+m2)

DoMethod(cForm,"Release")
Form_Main.SetFocus()
Return NIL
//---------------------------------------------------------



//---------------------------------------------------------
FUNCTION RandStr( nLen )
//---------------------------------------------------------
LOCAL cSet := "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
LOCAL cPass := ""
LOCAL i

FOR i := 1 TO nLen
    cPass += SubStr( cSet, Random( 52 ), 1 )
NEXT

RETURN cPass
//-----------------------------------------------------------



//-----------------------------------------------------------
FUNCTION Arq_Temporario()    // Gera nome de arquivo temporario
//-----------------------------------------------------------
RETURN "Y_"+ALLTRIM(RIGHT(NETNAME(),2))+ ALLTRIM(   STR(INT(SECOND()))  )
//-----------------------------------------------------------


Liberar memoria ao fechar Formulario com objeto criado

Enviado: 05 Set 2022 19:59
por JoséQuintas
Apenas chute, não deveria precisar:

Código: Selecionar todos

ACTIVATE WINDOW &cForm
RETURN oBrw
Insira um aList := {} antes do RETURN.

Mas geralmente a lista é copiada pro objeto, pode não ser a lista correta, apesar que array por default é passado por referência.
Tente também aSize( aList, 0 ) // ou 1
Mesmo caso: se é por referência, talvez := não resolva porque pode perder a referência.

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 08 Set 2022 09:53
por carlaoonline
Bom dia!
JoséQuintas escreveu:Insira um aList := {} antes do RETURN.
Seria uma forma de resolver (mesmo achando que ao destruir o objeto e dar Release no Form seria o suficiente)...Mas não funcionou tb.

Zerei o array aLista e limpei o oBrw:cargo, destrui o objeto, apaguei o controle TBrowse e apaguei o Form... a Memória libera um pouco mas muito longe de chegar perto da memória original antes da criação do TBrowse, E a cada CRIAÇÃO e DESTRUIÇÃO total de um novo Form com TBrowse vai ficando memória presa.... alternei a ordem quando possível em algumas vezes mas nada.

PORÉM percebi que após CRIAR e APAGAR vários TBrowses a ponto de ficar quase sem memória (com RELEASE em todos objetos exceto o form principal que só tem um botão), ao abrir um novo TBrowse (que teóricamente não haveria espaço) daí sim ele libera o suficiente para essa nova nova abertura só que ficou mais lento...talvez esteja gravando em disco ou a lentidão é em função de pouca memória mesmo.....


O sistema é um simples cadastro com milhares de clientes para captação de tele marketing, roda em qualquer PC.
O problema é que tem vários PCs velhos com 1 giga de memória...por isso a preocupação com a memória.


Por hora larguei de mão, nunca será aberto um tbrowse de 1 milhão de linhas...mas poderá ao longo do dia serem abertas e fechadas centenas de telas com centenas de registros em cada vez.....vou monitorar a memória e a rapidez do usuário, talvez force o fechamento e abertura do aplicativo caso diminuir muito a memória.

A cada abertura é criado um Form com nome diferente.... não cheguei a testar se abrir um novo Form com um mesmo nome já usado anteriormente acontece a mesma coisa....talvez eu crie uma lista com 5 nomes e limito a quantidade de listagens abertas simultaneamente... dai vou usando sempre os mesmo nomes de Forms se isso resolver.

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 26 Set 2022 18:20
por momente
Boa tarde!

Vc testou com HB_GCALL(TRUE) ?

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 17:23
por carlaoonline
Boa tarde!
momente escreveu:Vc testou com HB_GCALL(TRUE) ?
Inclui ele no programinha teste mas tb não rendeu....

Ao gerar aLista com 4.000.000 de elementos (por exemplo) e logo após dar release a criando novamente aLista com Zero elementos, mesmo usando esse comendo, a memória fica poluída, não libera a ponto de ficar como estava antes da criação do array.
Memória fica presa mesmo apagando a variável.
Memória fica presa mesmo apagando a variável.
Postei abaixo o programa teste. Se alguém quiser testar pode colocar ali 1 ou 3 ou 5 milhões de elementos pra ver, a memória sempre fica presa e só libera após sair do programa.

Código: Selecionar todos

#include "minigui.ch"

//---------------------------------------------------------
Function MAIN
//---------------------------------------------------------
Public nMemoriaInicial:=Alltrim(str(Memory(0)))
Public cMensagem:="Memoria Inicial (antes do Form Main) -> "+nMemoriaInicial+" Kb."+Hb_Eol()
Public aLista:={}, lineFeed:=Hb_Eol()  // +Hb_Eol()

DEFINE WINDOW Form_Main;
   TITLE "Form_Main" MAIN WIDTH 850 HEIGHT 360 ;
   ON GOTFOCUS Atualiza_botao() 
   @ 145,20 LABEL Lbl_1 WIDTH 160  HEIGHT 25 SIZE 12 VALUE "Quant. de elementos"
   @ 145, 170 GetBox Get_1 value 1000000 
   @ 135,320 button btn01 caption "Gerar array  -  (Memoria Inicial = "+nMemoriaInicial +")" Width 480 Height 50 action CriaArray()
END WINDOW

ON KEY ESCAPE of Form_Main ACTION Form_Main.Release
ACTIVATE WINDOW Form_Main

RETURN


//---------------------------------------------------------
Function CriaArray()
//---------------------------------------------------------
Local cForm:="FORM_"+ALLTRIM(SUBST(Arq_Temporario(),3,10))
Local F, nVoltas:=3, nMemoria

DECLARE WINDOW &(cForm) 

DEFINE WINDOW &cForm width 720 height 500 Title "cForm = "+cForm;
       ON INIT Atualiza_Botao();
       ON RELEASE Atualiza_Botao()
       @ 15, 20 LABEL Lbl_Memoria FontColor RED WIDTH 820  HEIGHT 480 SIZE 12;
       VALUE cMensagem
END WINDOW

cMensagem:=cMensagem+"Memoria apos criacao do Form_Main e do "+cForm+"  -> "+alltrim(str(memory(0)))+Hb_Eol()

FOR F=1 TO  nVoltas
    Preenche_Array(.T., cForm, nVoltas)   // .T. = Preenche     .F. = Zera ela
    Preenche_Array(.F., cForm, nVoltas)   // .T. = Preenche     .F. = Zera ela
NEXT

&(cForm).Lbl_Memoria.value:=GetProperty(cForm,"Lbl_Memoria","Value")+LineFeed+ ;
            "Antes da execucao de 'hb_gcAll()'   -> Memoria = "+alltrim(str(memory(0)))


DO EVENTS
hb_gcAll()
DO EVENTS
wApi_Sleep(500)       


nMemoria=Memory(0)

&(cForm).Lbl_Memoria.value:=GetProperty(cForm,"Lbl_Memoria","Value")+LineFeed+ ;
            "Apos a execucao de  'hb_gcAll()'   -> Memoria = "+alltrim(str(nMemoria))


&(cForm).Lbl_Memoria.value:=GetProperty(cForm,"Lbl_Memoria","Value")+LineFeed+Hb_Eol()+ ;
            "Diferenca de memoria = "+Alltrim(str(  Val(nMemoriaInicial)-nMemoria )) 

cMensagem="Memoria Inicial (antes do Form Main) -> "+nMemoriaInicial+" Kb."+Hb_Eol()

ON KEY ESCAPE OF &cForm ACTION &(cForm).Release
ACTIVATE WINDOW &cForm
RETURN 
//---------------------------------------------------------


//---------------------------------------------------------
Function Preenche_Array(lPreencher, cForm, nVoltas)
//---------------------------------------------------------
Static nVezes:=1
Local cString:="", nQuantElem:= GetProperty("Form_Main","Get_1","value")

IF lPreencher
   Atualiza_Botao()
   WAIT WINDOW "Adicionando "+transform(nQuantElem, '99 999 999 999')+" elementos em aLista{}. Etapa "+Alltrim(str(nVezes))+"/"+alltrim(str(nVoltas)) NOWAIT
   cString=Str(nVezes)+" - Antes de criar aLista com "+transform(nQuantElem, '99 999 999 999')+" elementos:  Memoria="+alltrim(str(memory(0)))
   cMensagem=cMensagem+LineFeed+cString
   FOR F := 1 TO nQuantElem
       AAdd( aLista, { F, Hb_RandomInt(99) , RandStr( 10 ), Date() - F, if( F % 2 == 0, TRUE, FALSE ), RandStr( 10 ), F*10   } )
   NEXT
   WAIT CLEAR
   cString=Str(nVezes)+" - APOS criar aLista com "+transform(nQuantElem, '99 999 999 999')+" elementos:  Memoria="+alltrim(str(memory(0)))
   cMensagem=cMensagem+LineFeed+cString
 ELSE
   Release aLista
   Public aLista:={}
   cString=Str(nVezes)+" - Apos Release, e nova criacao de 'aLista' com 'Zero' elementos:  Memoria="+alltrim(str(memory(0)))
   cMensagem=cMensagem+LineFeed+cString+Hb_Eol()
   nVezes=IF(nVezes=3,1,nVezes+1)
ENDIF
&(cForm).Lbl_Memoria.value:=cMensagem+Hb_Eol()
Atualiza_Botao()
Return
//---------------------------------------------------------


//---------------------------------------------------------
Function Atualiza_Botao()
//---------------------------------------------------------
SetProperty("Form_Main","btn01","caption","Gerar Array    ( Memoria Inicial = "+nMemoriaInicial+"    Memoria Atual = "+alltrim(str(memory(0)))+" )") 
Return NIL
//---------------------------------------------------------


//---------------------------------------------------------
FUNCTION RandStr( nLen )
//---------------------------------------------------------
LOCAL cSet := "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
LOCAL cPass := ""
LOCAL i

FOR i := 1 TO nLen
    cPass += SubStr( cSet, Random( 52 ), 1 )
NEXT

RETURN cPass
//-----------------------------------------------------------


//-----------------------------------------------------------
FUNCTION Arq_Temporario()    // Gera nome de arquivo temporario
//-----------------------------------------------------------
RETURN "Y_"+ALLTRIM(RIGHT(NETNAME(),2))+ ALLTRIM(   STR(INT(SECOND()))  )
//-----------------------------------------------------------





Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 17:52
por Itamar M. Lins Jr.
Olá!
Isso é BUG ou do BCC ou do xHarbour. Provavelmente do xHarbour.
Primeiro passo é ver uma Minigui com GCC e Harbour para testar e ver se vai dar o mesmo problema.
Parece que essa do link é com Harbour.
https://sourceforge.net/projects/hmgs-minigui/
Olhei é Harbour com BCC, já da para testar, se é bug do xHb.

Saudações,
Itamar M. Lins Jr.

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 19:38
por JoséQuintas
carlaoonline escreveu:Postei abaixo o programa teste. Se alguém quiser testar
minigui.png
Alguma idéia?

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:11
por JoséQuintas
Tem algum equivalente ao getbox pra testar na OOHG ?
Outro componente mais antigo da HMG.

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:17
por JoséQuintas
test.png
Sei lá se fiz certo no restante, mas bloqueei hb_gcAll()

Código: Selecionar todos

#include "minigui.ch"

MEMVAR cMensagem, aLista, F, nMemoriaInicial, LineFeed

PROCEDURE MAIN

   PUBLIC nMemoriaInicial := Alltrim( Str( Memory(0) ) )
   PUBLIC cMensagem := "Memoria Inicial (antes do Form Main) -> " + nMemoriaInicial + " Kb." + Hb_Eol()
   PUBLIC aLista := {}, lineFeed := Hb_Eol()  // +Hb_Eol()

   DEFINE WINDOW Form_Main ;
         TITLE "Form_Main" MAIN WIDTH 850 HEIGHT 360 ;
         ON GOTFOCUS Atualiza_botao()
      @ 145,20 LABEL Lbl_1 WIDTH 160  HEIGHT 25 SIZE 12 VALUE "Quant. de elementos"
      @ 145, 170 EDITBOX Get_1
      @ 135,320 button btn01 caption "Gerar array  -  (Memoria Inicial = "+nMemoriaInicial +")" Width 480 Height 50 action CriaArray()
   END WINDOW

   ON KEY ESCAPE of Form_Main ACTION Form_Main.Release
   ACTIVATE WINDOW Form_Main

   RETURN

FUNCTION CriaArray()

   LOCAL cForm := "FORM_" + ALLTRIM( SUBSTR( Arq_Temporario(), 3, 10 ) )
   LOCAL F, nVoltas := 3, nMemoria

   DECLARE WINDOW &( cForm )

   DEFINE WINDOW &cForm width 720 height 500 Title "cForm = " + cForm ;
         ON INIT Atualiza_Botao() ;
         ON RELEASE Atualiza_Botao()
      @ 15, 20 LABEL Lbl_Memoria FontColor RED WIDTH 820  HEIGHT 480 SIZE 12 ;
         VALUE cMensagem
   END WINDOW

   cMensagem := cMensagem + "Memoria apos criacao do Form_Main e do " + cForm + "  -> " + ;
      alltrim( Str( memory(0) ) ) + Hb_Eol()

   FOR F = 1 TO  nVoltas
      Preenche_Array( .T., cForm, nVoltas )   // .T. = Preenche     .F. = Zera ela
      Preenche_Array( .F., cForm, nVoltas )   // .T. = Preenche     .F. = Zera ela
   NEXT

   &( cForm ).Lbl_Memoria.value := GetProperty( cForm, "Lbl_Memoria", "Value" ) + LineFeed + ;
      "Antes da execucao de 'hb_gcAll()'   -> Memoria = " + alltrim( Str( memory(0) ) )

   DO EVENTS
   //hb_gcAll()
   //DO EVENTS
   wApi_Sleep(500)

   nMemoria := Memory(0)

   &( cForm ).Lbl_Memoria.value := GetProperty( cForm, "Lbl_Memoria", "Value" ) + LineFeed + ;
      "Apos a execucao de  'hb_gcAll()'   -> Memoria = " + alltrim( Str( nMemoria ) )

   &( cForm ).Lbl_Memoria.value := GetProperty( cForm, "Lbl_Memoria", "Value" ) + LineFeed + Hb_Eol() + ;
      "Diferenca de memoria = " + Alltrim( Str( Val( nMemoriaInicial ) - nMemoria ) )

   cMensagem := "Memoria Inicial (antes do Form Main) -> " + nMemoriaInicial + " Kb." + Hb_Eol()

   ON KEY ESCAPE OF &cForm ACTION &( cForm ).Release
   ACTIVATE WINDOW &cForm

   RETURN Nil

FUNCTION Preenche_Array( lPreencher, cForm, nVoltas )

   STATIC nVezes := 1
   LOCAL cString, nQuantElem := Val( GetProperty( "Form_Main", "Get_1", "value" ) )

   IF lPreencher
      Atualiza_Botao()
      msgbox( "Adicionando " + transform( nQuantElem, '99 999 999 999' ) + ;
         " elementos em aLista{}. Etapa " + Alltrim( Str( nVezes ) ) + "/" + alltrim( Str( nVoltas ) )  )
      cString := Str( nVezes ) + " - Antes de criar aLista com " + transform( nQuantElem, '99 999 999 999' ) + ;
      " elementos:  Memoria=" + alltrim( Str( memory(0) ) )
      cMensagem := cMensagem + LineFeed + cString
      FOR F := 1 TO nQuantElem
         AAdd( aLista, { F, Hb_RandomInt(99) , RandStr( 10 ), Date() - F, if( F % 2 == 0, TRUE, FALSE ), RandStr( 10 ), F * 10   } )
      NEXT
      MsgBox( Str( nVezes ) + " - APOS criar aLista com " + transform( nQuantElem, '99 999 999 999' ) + " elementos:  Memoria=" + alltrim( Str( memory(0) ) ) )
      cMensagem := cMensagem + LineFeed + cString
   ELSE
      RELEASE aLista
      PUBLIC aLista:={}

      cString = Str( nVezes ) + " - Apos Release, e nova criacao de 'aLista' com 'Zero' elementos:  Memoria=" + alltrim( Str( memory(0) ) )
      cMensagem = cMensagem + LineFeed + cString + Hb_Eol()
      nVezes = IF( nVezes = 3, 1, nVezes + 1 )
   ENDIF
   &( cForm ).Lbl_Memoria.value := cMensagem + Hb_Eol()
   Atualiza_Botao()

   RETURN Nil

FUNCTION Atualiza_Botao()

   SetProperty( "Form_Main", "btn01", "caption", "Gerar Array    ( Memoria Inicial = " + nMemoriaInicial + "    Memoria Atual = " + alltrim( Str( memory(0) ) ) + " )" )

   RETURN Nil

FUNCTION RandStr( nLen )

   LOCAL cSet := "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
   LOCAL cPass := ""
   LOCAL i

   FOR i := 1 TO nLen
      cPass += Substr( cSet, Random( 52 ), 1 )
   NEXT

   RETURN cPass

FUNCTION Arq_Temporario()    // Gera nome de arquivo temporario

   RETURN "Y_" + ALLTRIM( RIGHT( NETNAME(), 2 ) ) + AllTrim( Str( INT( SECOND() ) ) )
Usei Harbour 3.4 + OOHG + mingw 7.3

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:27
por JoséQuintas
mem.png
Sei lá... o array tá no espaço?

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:36
por Itamar M. Lins Jr.
Olá!
Olha ai:

Código: Selecionar todos

MEMORY( HB_MEM_USEDMAX )
o hbmemory.ch

Código: Selecionar todos

/* NOTE: This file is also used by C code. */

#ifndef HB_MEMORY_CH_
#define HB_MEMORY_CH_

/* Parameters for Memory() function */

/* Standard */
#define HB_MEM_CHAR             0   /* Free Variable Space (KB) */
#define HB_MEM_BLOCK            1   /* Largest String (KB) */
#define HB_MEM_RUN              2   /* RUN Memory (KB) */

/* CA-Cl*pper undocumented */
#define HB_MEM_VM               3   /* Virtual Memory (KB) */
#define HB_MEM_EMS              4   /* Free Expanded Memory (KB) (?) */
#define HB_MEM_FM             101   /* Fixed Memory/Heap (KB) (?) */
#define HB_MEM_FMSEGS         102   /* Segments in Fixed Memory/Heap (?) */
#define HB_MEM_SWAP           103   /* Free Swap Memory (KB) */
#define HB_MEM_CONV           104   /* Free Conventional (KB) */
#define HB_MEM_EMSUSED        105   /* Used Expanded Memory (KB) (?) */

/* Harbour extensions */
#define HB_MEM_USED          1001   /* Memory used (bytes) */
#define HB_MEM_USEDMAX       1002   /* Maximum memory used (bytes) */
#define HB_MEM_STACKITEMS    1003   /* Total items on the stack */
#define HB_MEM_STACK         1004   /* Total memory size used by the stack (bytes) */
#define HB_MEM_STACK_TOP     1005   /* Total items currently on the stack */
#define HB_MEM_BLOCKS        1007   /* Total number of memory blocks allocated */
#define HB_MEM_STATISTICS    1008   /* Return non 0 value if FM statistic is enabled */
#define HB_MEM_CANLIMIT      1009   /* Return non 0 value if used memory limit is supported */
#endif /* HB_MEMORY_CH_ */

Saudações,
Itamar M. Lins Jr.

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:37
por JoséQuintas
Sei lá também...
Mas seria interessante testar no XHarbour.

Código: Selecionar todos


PROCEDURE Main

   LOCAL F, aLista := {}

   SetMode(40,100)
   CLS
   ? "Antes do array: " + Ltrim( Str( Memory(0) ) )

   FOR F := 1 TO 1000000
      AAdd( aLista, { F, Hb_RandomInt(99) , hb_RandomInt(99), Date() - F, F % 2 == 0, hb_RandomInt(99), F * 10   } )
   NEXT
   ? "Depois do array: " + Ltrim( Str( Memory(0) ) )
   aLista := {}
   ( aLista )
   ? "Zerando: " + Ltrim( Str( Memory(0) ) )

   Inkey(0)

   RETURN
hb.png
hb.png (4.67 KiB) Exibido 4664 vezes

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:41
por JoséQuintas
Aí complicou.... se é esse teste mesmo.
test.png

Código: Selecionar todos



#define MEM_TEST 1002

PROCEDURE Main

   LOCAL F, aLista := {}

   SetMode(40,100)
   CLS
   ? "Antes do array: " + Ltrim( Str( Memory(MEM_TEST) ) )

   FOR F := 1 TO 1000000
      AAdd( aLista, { F, Hb_RandomInt(99) , hb_RandomInt(99), Date() - F, F % 2 == 0, hb_RandomInt(99), F * 10   } )
   NEXT
   ? "Depois do array: " + Ltrim( Str( Memory(MEM_TEST) ) )
   aLista := {}
   ( aLista )
   ? "Zerando: " + Ltrim( Str( Memory(MEM_TEST) ) )

   Inkey(0)

   RETURN

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:45
por JoséQuintas
E isso leva a outra coisa.... O MEU PROBLEMA DE ESTOURAR LIMITES.
Uso muito array.
E agora?

Liberar memoria ao fechar Formulario com objeto criado

Enviado: 27 Set 2022 20:47
por JoséQuintas
Itamar, por favor, teste isso no Harbour 3.2.