Libération de zone mémoire

Sujets variés concernant le développement en PureBasic
Avatar de l’utilisateur
DarkVader
Messages : 95
Inscription : mer. 11/juil./2007 10:56

Libération de zone mémoire

Message 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 ?
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: Libération de zone mémoire

Message 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)
ImageImage
Avatar de l’utilisateur
DarkVader
Messages : 95
Inscription : mer. 11/juil./2007 10:56

Re: Libération de zone mémoire

Message 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 ?
Fred
Site Admin
Messages : 2808
Inscription : mer. 21/janv./2004 11:03

Re: Libération de zone mémoire

Message par Fred »

Non, pas a la fin d'une procedure, seulement quand le programme se termine ou que la DLL is dechargée.
Avatar de l’utilisateur
DarkVader
Messages : 95
Inscription : mer. 11/juil./2007 10:56

Re: Libération de zone mémoire

Message 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 ?
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Re: Libération de zone mémoire

Message 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:
Fred
Site Admin
Messages : 2808
Inscription : mer. 21/janv./2004 11:03

Re: Libération de zone mémoire

Message par Fred »

:lol:
Avatar de l’utilisateur
DarkVader
Messages : 95
Inscription : mer. 11/juil./2007 10:56

Re: Libération de zone mémoire

Message par DarkVader »

Bravo, c'est bien de troller un thread mais ça ne répond pas à ma 2ème question :mrgreen:
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Re: Libération de zone mémoire

Message 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:
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: Libération de zone mémoire

Message 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.
ImageImage
Avatar de l’utilisateur
DarkVader
Messages : 95
Inscription : mer. 11/juil./2007 10:56

Re: Libération de zone mémoire

Message par DarkVader »

Code : Tout sélectionner

if *buffer 
   freememory(*buffer)
endif
n'est-il pas équivalent ?
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: Libération de zone mémoire

Message 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
ImageImage
Avatar de l’utilisateur
DarkVader
Messages : 95
Inscription : mer. 11/juil./2007 10:56

Re: Libération de zone mémoire

Message 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.
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: Libération de zone mémoire

Message 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
ImageImage
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Libération de zone mémoire

Message 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é"


Répondre