Page 1 sur 2

Libération de zone mémoire

Publié : sam. 14/mai/2011 9:52
par DarkVader
Bonjour,

Il est spécifié dans la doc PB que toutes les zones mémoires n'ayant pas été libérée par un FreeMemory sont libérées en fin de programme :
cela sous-entend-il que si un pointeur de variable locale est déclaré avec Protected dans une procedureDll
alors la zone mémoire affectée au pointeur dans la procedure sera automatiquement libérée après ProcedureReturn ?

Re: Libération de zone mémoire

Publié : sam. 14/mai/2011 11:12
par case
dans tout les cas la variable est remise a zero en sortant de la procédure.
protected ne conserve pas le contenu de la variable mais permet d'avoir une variable locale avec le même nom qu'une variable globale sans modifier l'une ou l'autre.

Code : Tout sélectionner

Global Z
Global a=50

Procedure blah()
   Protected a
   a +z ; on ajoute 10 a z a devrait etre 10 20 30 40 50 60  si la variable était conservée
   Debug "A protected="+Str(a)
EndProcedure
;
Debug   "A global      ="+Str(a)
z =10
For k=1 To 10
   blah()
Next
Debug   "A global      ="+Str(a)

Re: Libération de zone mémoire

Publié : sam. 14/mai/2011 11:27
par DarkVader
Je parle zone mémoire

Dans ce contexte

Code : Tout sélectionner

proceduredll xxx()
protected *buffer=AllocateMemory(1000)

endprocedure
est-ce qu'un freememory est opéré automatiquement sur *buffer à la sortie de la procédure ?

Re: Libération de zone mémoire

Publié : sam. 14/mai/2011 11:36
par Fred
Non, pas a la fin d'une procedure, seulement quand le programme se termine ou que la DLL is dechargée.

Re: Libération de zone mémoire

Publié : sam. 14/mai/2011 13:46
par DarkVader
Merci,
c'est ce que je craignais.

En fait, dans une procédure j'ai écrit la gestion d'erreurs suivante:

Code : Tout sélectionner

ProcedureDll xxxx()
   Protected *buffer

   OnErrorGoto (?ProcErrHandler)

;.... traitement
Allocate
FreeMemory

; ... end traitement
ProcedureReturn yyyy

ProcErrHandler:
   ;traitement erreur
   ...

   FreeMemory *Buffer
   OnErrorDefault()
   ProcedureReturn 0
EndProcedure
et j'ai du coup un nouvelle question :
Dans le cas où une erreur se produise avant que l'allocation de *buffer ait eu lieu
est-ce que FreeMemory (exécuté dans ProcErrHandler) lèvera une nouvelle exception ?
En bref, le traitement décrit est-il correct ?

Re: Libération de zone mémoire

Publié : sam. 14/mai/2011 16:37
par Chris
Fred a écrit :Non, pas a la fin d'une procedure, seulement quand le programme se termine ou que la DLL is dechargée.
Fred, il faudrait voir à venir un peu plus ici, et un peu moins chez les anglais, ça se ressent dans ton orthographe.

C'est le début du syndrome JCVD.
Dans pas longtemps, tu vas être "aware" :mrgreen:

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 9:54
par Fred
:lol:

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 15:09
par DarkVader
Bravo, c'est bien de troller un thread mais ça ne répond pas à ma 2ème question :mrgreen:

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 15:17
par Chris
DarkVader a écrit :Bravo, c'est bien de troller un thread mais ça ne répond pas à ma 2ème question :mrgreen:
Ooops!...Désolé! :oops:
Mais c'était difficile de résister. :wink:

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 16:39
par case
DarkVader a écrit :Merci,
c'est ce que je craignais.

En fait, dans une procédure j'ai écrit la gestion d'erreurs suivante:

Code : Tout sélectionner

ProcedureDll xxxx()
   Protected *buffer

   OnErrorGoto (?ProcErrHandler)

;.... traitement
Allocate
FreeMemory

; ... end traitement
ProcedureReturn yyyy

ProcErrHandler:
   ;traitement erreur
   ...

   FreeMemory *Buffer
   OnErrorDefault()
   ProcedureReturn 0
EndProcedure
et j'ai du coup un nouvelle question :
Dans le cas où une erreur se produise avant que l'allocation de *buffer ait eu lieu
est-ce que FreeMemory (exécuté dans ProcErrHandler) lèvera une nouvelle exception ?
En bref, le traitement décrit est-il correct ?
a mon avis cela créera une autre erreur vu que la mémoire n'est pas allouée et que tu veux libérer une mémoire non allouée
pour éviter cela tu peux faire un ReAllocateMemory(*buffer,1) avant de libérer la mémoire

Code : Tout sélectionner

ReAllocateMemory(*buffer,1)
freememory(*buffer)
car dans le cas ou la mémoire est bien allouée elle est ré-allouée donc ca n'est pas génant. et dans le cas ou elle n'est pas déja allouée elle l'est maintenant et peut être libérée sans erreur.

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 17:01
par DarkVader

Code : Tout sélectionner

if *buffer 
   freememory(*buffer)
endif
n'est-il pas équivalent ?

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 17:34
par case
non car si par exemple tu alloue un buffer a un moment donné dans ta variable *buffer celle ci contiens toujours l'adresse memoire du buffer meme si tu l'a libéré

Code : Tout sélectionner

*buffer=AllocateMemory(2000) 
Debug  *buffer
FreeMemory(*buffer)
;
;
;
If *buffer
   FreeMemory(*buffer)
EndIf
ou alors il faut effacer le contenu de *buffer en même temps que tu libère la mémoire

Code : Tout sélectionner

*buffer=AllocateMemory(2000) 
Debug  *buffer
FreeMemory(*buffer):*buffer=0
;
;
;
If *buffer
   FreeMemory(*buffer)
EndIf

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 18:04
par DarkVader
OK
Je vais plutôt réinitialiser systématiquement *buffer à 0 après chaque FreeMemory
pour dans la gestion d'erreurs pouvoir effectuer le test.
Ça me semble plus propre.

Merci.

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 18:49
par case
tu peux passer par une macro

Code : Tout sélectionner

Macro FreeMem (var)
   FreeMemory(var)
   var=0
EndMacro


*buffer=AllocateMemory(500)
debug *buffer
FreeMem(*buffer)
debug *buffer

Re: Libération de zone mémoire

Publié : dim. 15/mai/2011 20:31
par G-Rom
Tu peut aussi utilisé un système de pointeur intelligent , le pointeur vérifie qu'aucune variable ne pointe sur lui.

Code : Tout sélectionner

; Pointeur intéligent


Structure smartPointer
  mPointer.i
  mNbLink.i
  List mPtrList.i()
EndStructure


Procedure.i New(size.i)
  *sp.smartPointer = AllocateMemory(SizeOf(smartPointer))
  *sp\mPointer     = AllocateMemory(size)
  *sp\mNbLink      = 0
  InitializeStructure(*sp,SmartPointer)
  
  ProcedureReturn *sp
EndProcedure


Procedure.b Delete(*smartPointer.smartPointer)
  
  If *smartPointer
    
    ForEach *smartPointer\mPtrList()
      Pointer = *smartPointer\mPtrList()
      Value   = PeekI(Pointer)
      If Value <> *smartPointer\mPointer
        *smartPointer\mNbLink - 1
      EndIf 
    Next 
    
    If *smartPointer\mNbLink < 0
      *smartPointer\mNbLink = 0
    EndIf 
    
    
    If *smartPointer\mNbLink = 0
      FreeMemory(*smartPointer\mPointer)
      FreeMemory(*smartPointer)
      ProcedureReturn #True 
    EndIf  
  EndIf 
  
  
  Debug "Impossible de libérer le smartPointer , il est lié "+Str(*smartPointer\mNbLink)+ " fois."
  
  ProcedureReturn #False 
  
EndProcedure


Procedure Assign(*smartPointer.smartPointer, pointer.i)
  If *smartPointer<>0
   AddElement(*smartPointer\mPtrList())
    *smartPointer\mPtrList() = pointer
    PokeI(pointer,*smartPointer\mPointer)
    *smartPointer\mNbLink + 1
  EndIf 
EndProcedure


Procedure GetNbLink(*smartPointer.smartPointer)
  If *smartPointer<>0
    ProcedureReturn *smartPointer\mNbLink
  EndIf 
EndProcedure


Procedure SmartPointer_PokeI(*smartPointer.SmartPointer, value.i)
  If *smartPointer
    If *smartPointer\mNbLink > 0
      PokeI(*smartPointer\mPointer,value)
    EndIf 
  EndIf 
EndProcedure


Procedure.i SmartPointer_PeekI(*smartPointer.SmartPointer)
  If *smartPointer
    If *smartPointer\mNbLink > 0
      ProcedureReturn PeekI(*smartPointer\mPointer)
    EndIf 
  EndIf 
EndProcedure




SmartPointer = New(1000) ; Allocation de 1000 bytes
*PointeurA = #Null
*PointeurB = #Null

Assign(SmartPointer, @*PointeurA)
Assign(SmartPointer, @*PointeurB)


; Ecriture dans la zone mémoire
PokeI(*PointeurA, 527)
;ou comme ca :
SmartPointer_PokeI(SmartPointer,527)

; Lecture dans la zone mémoire
Debug PeekI(*PointeurB) 
; ou comme ca :
Debug SmartPointer_PeekI(SmartPointer)



Delete(SmartPointer) ; On ne peut pas l'effacer ! , il est lié 2 fois !
                     ; Le smartPointer existe toujours.


*Hacking   = *PointeurA ; Comportement dangereux , *Hacking n'est pas répertorié dans le smart pointer , a évité donc !
*PointeurA = #Null ; on coupe les liens avec le smartPointer
*PointeurB = #Null 

Delete(SmartPointer) ; On libère la zone mémoire , il n'est plus lié, donc c'est bon.

Debug "Le smartPointer est bien effacé"