comment débuguer des fuites de mémoire (memory leak) ?

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

comment débuguer des fuites de mémoire (memory leak) ?

Message par Golfy »

Si j'écris ça, le code ne plante pas... pour autant dans quelques jours il plantera sans savoir pourquoi (enfin, dans le cas ci-dessous, je sais pourquoi :wink: ).
Existe-t'il une application ou un mode debug qui permette de surveiller la quantité de mémoire utilisée sur du long terme ?

Code : Tout sélectionner

cnt = 0
Repeat
  a= AllocateMemory(200)
  cnt + 200
  Debug "Malloc "+Str(a)+"   ("+Str(cnt)+" oct.)"
  Delay(100)
ForEver
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par kernadec »

bonjour Golfy

peut être une solution

Cordialement

Code : Tout sélectionner

cnt = 0
Repeat
  If cnt<20000              ; la mémoire physique à toujours une limite
    a= AllocateMemory(200)
    cnt + 200
  Else
    ; effectuer un stockage et recommencer la boucle à 0
  EndIf
  Debug "Malloc "+Str(a)+"   ("+Str(cnt)+" oct.)"
  Delay(100)
ForEver
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par Golfy »

Merci Kernadec, mais j'ai dû mal m'exprimer... je pensais à une procédure qui serait appelé régulièrement et qui contiendrait un AllocateMemory mais (suite à une négligence du programmeur oublieux) pas de FreeMemory !

Ma question est donc, comment tester son code et surveiller sa mémoire ?
Certains développeurs m'ont parlé de Valgrind mais je ne sais même pas s'il est compatible avec Purebasic...
J'ai trouvé un programme pour Windows aussi : http://winleak.sourceforge.net/ (mais n'a pas marché sous Win7 64b)
PS : J'ai également vu ce post (en anglais) : http://www.purebasic.fr/english/viewtopic.php?t=34577
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par kernadec »

ton exemple devrait choisir une taille mémoire conséquente pour la tache a effectuer
et utiliser ReAllocateMemory()

comme dans l' exemple du manuel :

Code : Tout sélectionner

*MemoireID = AllocateMemory(1000)
  PokeS(*MemoireID, "Stocke cette chaîne")
  ; faire quelque chose en plus avec ça ici...
  ;
  *NouvelleMemoireID = ReAllocateMemory(*MemoireID, 2000) ; besoin de plus de mémoire
  If *NouvelleMemoireID
    ; maintenant travailler avec *NouvelleMemoireID avec une taille de 2000 octets
    Debug "L'ancien contenu est toujours là :"
    Debug PeekS(*NouvelleMemoireID)
    ;
    FreeMemory(*NouvelleMemoireID)
  Else
    ; le redimensionnement a échoué, continuons de travailler avec *MemoireID (de taille 1000 octets)
    ;
    FreeMemory(*MemoireID)
  EndIf

sinon pour connaitre la taille globale de la RAM
il y a cet exemple dans "Codearchiv"

Cordialement

Code : Tout sélectionner

; German forum: http://www.purebasic.fr/german/archive/viewtopic.php?t=1776
; Author: Thorsten
; Date: 23. July 2003
; OS: Windows
; Demo: No

Procedure.f FreeRAM()  

   ;Eine leere Struktur erstellen 
   Info.MEMORYSTATUS 
    
   ;Die Größe der Struktur ermitteln und in ihr selbst speichern 
   Info\dwLength = SizeOf(MEMORYSTATUS) 
    
   ;Vom System die Speicherinfos hohlen 
   GlobalMemoryStatus_(@Info) 
    
   ;Zuweisen der Daten 
   Total.f = Info\dwTotalPhys 
   Free.f = Info\dwAvailPhys    
    
   ;Rückgabe der Ergebnisse, prozentual 
   ProcedureReturn (100 / Total) * Free 
EndProcedure 

Debug FreeRAM()  ; Give free memory in percent
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par graph100 »

Il y a un moment j'ai du deboger un memory leak dans mon prog de lecture de bd. Pour détecter la fuite de mémoire j'ai tout simplement utilisé le gestionnaire des tâches. Il n'est pas extrêmement rapide d'actualisation, mais la quantité de mémoire utilisée est affichée et si elle tend à croitre, ça va se voir.

Le bug en question n'était pas causé par un allocatememory(), mais par la création d'une image avec #pb_any qui n'était pas libérée.
Je ne crois pas qu'on puisse vraiment utiliser d'outils spéciaux pour trouver une fuite mémoire. Il n'y a que nous qui puissions distinguer le comportement qu'on défini comme anormal.
A nous de définir quelle est la manipulation qui provoque l'augmentation de mémoire anormale, puis de la retrouver dans le code.

C'est sur que c'est chiant quand ça arrive, et qu'on ne peux pas pas toujours les prévoir (celle que j'ai trouvé était tout à fait improbable, puisqu'il fallait lire plus de 1000 images de la bd tout en leur faisant subir une rotation... :? )

bon courage !
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par Golfy »

Je pensais à un outil basic comme le code ci-dessous (mais j'ai un problème avec le "prototypage")

Code : Tout sélectionner


Prototype.l GetProcessMemoryInfo_(pr.l, *p, cb.l)
 
 Procedure.l GetMemoryUsage(kilobytes.b=#True)
   Structure PROCESS_MEMORY_COUNTERS
      cb.l;DW
      PageFaultCount.l;DW
      PeakWorkingSetSize.l;SIZE_T
      WorkingSetSize.l;SIZE_T
      QuotaPeakPagedPoolUsage.l;SIZE_T
      QuotaPagedPoolUsage.l;SIZE_T
      QuotaPeakNonPagedPoolUsage.l;SIZE_T
      QuotaNonPagedPoolUsage.l;SIZE_T
      PagefileUsage.l;SIZE_T
      PeakPagefileUsage.l;SIZE_T
   EndStructure
   
   Static GetProcessMemoryInfo_.GetProcessMemoryInfo_
   Static PSAPI
   If Not GetProcessMemoryInfo_
      If Not PSAPI
         PSAPI=OpenLibrary(#PB_Any, "PSAPI.DLL")
      EndIf
      If PSAPI
         GetProcessMemoryInfo_=GetFunction(PSAPI, "GetProcessMemoryInfo")
      EndIf
   EndIf
   If GetProcessMemoryInfo_
      Protected p.PROCESS_MEMORY_COUNTERS
      GetProcessMemoryInfo_(GetCurrentProcess_(), @p, SizeOf(PROCESS_MEMORY_COUNTERS))
      
      If kilobytes
         ProcedureReturn (p\WorkingSetSize+p\PagefileUsage) /1024
      Else
         ProcedureReturn (p\WorkingSetSize + p\PagefileUsage) 
      EndIf
   EndIf
EndProcedure 
;-----------------------
f$   = OpenFileRequester("Programme a tester (Leak Memory)","*.exe","EXE|*.exe",0)
r    = RunProgram(f$,"","",#PB_Program_Open)
If r
	pr.l = ProgramID(r)
	
	a = 0
	Repeat
		b = GetMemoryUsage(#True)
		Debug b-a
		a = b
		Delay(500)
	ForEver
EndIf
CloseProgram(r)
Un peu d'aide pour utiliser la fonction magique de lecture de la taille et on pourra faire des truc sympa (graphe dans le temps par exemple) et filer le bébé sur les forums Purebasic 8)
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par graph100 »

je ne comprend pas ta ligne :

Code : Tout sélectionner

GetProcessMemoryInfo_(GetCurrentProcess_(), @p, SizeOf(PROCESS_MEMORY_COUNTERS))
pourquoi tu utilises GetCurrentProcess_() ??
Tu veux pourtant monitorer le programme que tu as lancé avec runprogram ? non ?
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par Golfy »

même en mettant pr.l en global et en remplaçant, ça ne change rien... et moi, je ne comprend pas la ligne

Code : Tout sélectionner

Prototype.l GetProcessMemoryInfo_(pr.l, *p, cb.l)
et où se trouve *p (que je n'ai jamais définie)

Code : Tout sélectionner

   If GetProcessMemoryInfo_
      Protected p.PROCESS_MEMORY_COUNTERS
      GetProcessMemoryInfo_(GetCurrentProcess_(), @p, SizeOf(PROCESS_MEMORY_COUNTERS))
Y'a aussi un code de Jacobus (mais quand j'ai essayé, j'ai pas vu le champ concernant la mémoire être rempli) :

Code : Tout sélectionner

Global pr.l

;Prototype.l GetProcessMemoryInfo_(pr.l, *p, cb.l)
 
ProcedureDLL GetProcessMemory(PID.l)
   Structure PROCESS_MEMORY_COUNTERS
      cb.l;DW
      PageFaultCount.l;DW
      PeakWorkingSetSize.l;SIZE_T
      WorkingSetSize.l;SIZE_T
      QuotaPeakPagedPoolUsage.l;SIZE_T
      QuotaPagedPoolUsage.l;SIZE_T
      QuotaPeakNonPagedPoolUsage.l;SIZE_T
      QuotaNonPagedPoolUsage.l;SIZE_T
      PagefileUsage.l;SIZE_T
      PeakPagefileUsage.l;SIZE_T
    EndStructure
    
  pmc.PROCESS_MEMORY_COUNTERS   
  hProcess.l  = OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ, #False, PID) 
   
  If OpenLibrary(0,"PSAPI.DLL")     
    *F=GetFunction(0,"GetProcessMemoryInfo") 
    If *F 
      CallFunctionFast(*F,hProcess,@pmc,SizeOf(pmc))    
       GetProcessusSize = pmc\WorkingSetSize               
    Else  
      CloseLibrary(0) 
      End 
    EndIf 
  Else 
    End 
  EndIf 
  
  ProcedureReturn GetProcessusSize 
  
EndProcedure

;-----------------------
f$   = OpenFileRequester("Programme a tester (Leak Memory)","*.exe","EXE|*.exe",0)
r    = RunProgram(f$,"","",#PB_Program_Open)
If r
	pr.l = ProgramID(r)
	
	a = 0
	Repeat
		;b = GetMemoryUsage(#False)
		b= GetProcessMemory(pr.l)
		Debug b-a
		a = b
		Delay(500)
	ForEver
EndIf
CloseProgram(r)
Post :
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par Golfy »

Peut-être un début d'explication (thanks Microsoft) :
Starting with Windows 7 and Windows Server 2008 R2, Psapi.h establishes version numbers for the PSAPI functions. The PSAPI version number affects the name used to call the function and the library that a program must load.
If PSAPI_VERSION is 2 or greater, this function is defined as K32GetProcessMemoryInfo in Psapi.h and exported in Kernel32.lib and Kernel32.dll. If PSAPI_VERSION is 1, this function is defined as GetProcessMemoryInfo in Psapi.h and exported in Psapi.lib and Psapi.dll as a wrapper that calls K32GetProcessMemoryInfo.
Programs that must run on earlier versions of Windows as well as Windows 7 and later versions should always call this function as GetProcessMemoryInfo. To ensure correct resolution of symbols, add Psapi.lib to the TARGETLIBS macro and compile the program with -DPSAPI_VERSION=1. To use run-time dynamic linking, load Psapi.dll.

Code : Tout sélectionner

  ;If OpenLibrary(0,"PSAPI.DLL") ; winXP
  If OpenLibrary(0,"KERNEL32.DLL") ; Win7
    ;*F=GetFunction(0,"GetProcessMemoryInfo") ; WinXP
    *F=GetFunction(0,"K32GetProcessMemoryInfo") ;Win7
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par graph100 »

Ouais, non mais le code de Jacobus fonctionne très bien. Je suis sous win7, et pas de soucis.

je l'ai juste modifié pour pas aller ouvrir la dll à chaque appel de la fonction.

Code : Tout sélectionner

ProcedureDLL GetProcessMemory(PID.l)
	Structure PROCESS_MEMORY_COUNTERS
		cb.l;DW
		PageFaultCount.l;DW
		PeakWorkingSetSize.l;SIZE_T
		WorkingSetSize.l;SIZE_T
		QuotaPeakPagedPoolUsage.l;SIZE_T
		QuotaPagedPoolUsage.l;SIZE_T
		QuotaPeakNonPagedPoolUsage.l;SIZE_T
		QuotaNonPagedPoolUsage.l;SIZE_T
		PagefileUsage.l;SIZE_T
		PeakPagefileUsage.l;SIZE_T
	EndStructure
	
	pmc.PROCESS_MEMORY_COUNTERS   
	hProcess.l  = OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ, #False, PID)
	
	Static *F.i
	
	If *F=0
		If OpenLibrary(0,"PSAPI.DLL")
			*F=GetFunction(0,"GetProcessMemoryInfo")
			If *F=0
				CloseLibrary(0)
				ProcedureReturn -1 ; erreur
			EndIf
		Else
			ProcedureReturn -1 ; erreur
		EndIf
	EndIf
	
	CallFunctionFast(*F,hProcess,@pmc,SizeOf(pmc))
	
	ProcedureReturn pmc\WorkingSetSize
	
EndProcedure

;-----------------------
f$   = OpenFileRequester("Programme a tester (Leak Memory)","*.exe","EXE|*.exe",0)
r    = RunProgram(f$,"","",#PB_Program_Open)
If r
	pr.l = ProgramID(r)
	
	a = 0
	Repeat
		;b = GetMemoryUsage(#False)
		b= GetProcessMemory(pr.l)
		Debug b-a
		a = b
		Delay(100)
	ForEver
EndIf
CloseProgram(r)
teste le avec un code du genre :

Code : Tout sélectionner

For i = 0 To 8000
	AllocateMemory(100000)
	Delay(500)
	
Next
Moi, ça m'affiche les allocations de mémoire comme il faut.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par kernadec »

bonjour
Merci à vous d'avoir retrouvé ce code très utile, excellent.

Cordialement
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par Mesa »

Ça ne répond pas à la question mais pour voir les fuites de mémoire en cours de développement d'un soft, pensez au 'purificateur' de PureBasic :
http://purebasic.developpez.com/faq/?pa ... rificateur

Mesa.
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par Golfy »

De pire en pire... mais ça va finir par marcher :roll:
Voici un petit programme utilisable... mais qui plante rapidement (gestion des évènements :?: )
__________
Le programme attend la sélection d'un programme et le lance (le bouton STOP contient alors le PID du program). L'éditeur contient normalement la date et l'écart de mémoire mesuré.
__________
@Graph100 : j'ai utilisé ta procédure

Code : Tout sélectionner

Global Window_0
Global Image_0, B_Choix, B_Quit, B_Stop, C_Second, Text_0, Text_1, B_Log, B_Help, Editor_0

Global r, pr.l, f$

Procedure InitWindow_0()
  Img = CreateImage(#PB_Any, 580, 130)

  Window_0 = OpenWindow(#PB_Any, 0, 0, 600, 270, "PB Leak Finder", #PB_Window_SystemMenu)
  Image_0 = ImageGadget(#PB_Any, 10, 110, 580, 130, ImageID(Img), #PB_Image_Border)
  B_Choix = ButtonGadget(#PB_Any, 10, 10, 100, 20, "Choose EXE...")
  B_Quit = ButtonGadget(#PB_Any, 10, 70, 100, 20, "Quit", #PB_Button_Default)
  B_Stop = ButtonGadget(#PB_Any, 120, 10, 50, 50, "STOP",#PB_Button_MultiLine)
  C_Second = ComboBoxGadget(#PB_Any, 490, 10, 70, 20)
  Text_0 = TextGadget(#PB_Any, 410, 10, 70, 20, "Check every")
  Text_1 = TextGadget(#PB_Any, 570, 10, 20, 20, "sec.")
  B_Log = ButtonGadget(#PB_Any, 10, 40, 100, 20, "Please log-it", #PB_Button_Right | #PB_Button_Toggle)
  B_Help = ButtonGadget(#PB_Any, 120, 70, 50, 20, "?")
  Editor_0 = EditorGadget(#PB_Any, 180, 10, 220, 80)
EndProcedure

Procedure Window_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Gadget
      Select EventGadget()
        Case B_Stop
          If r
            CloseProgram(r)
            r = 0
          Else
            MessageRequester("Nothing to close","Nothing to close")
          EndIf
          
        Case B_Choix
          f$   = OpenFileRequester("Programme a tester (Leak Memory)","*.exe","EXE|*.exe",0)
          r    = RunProgram(f$,"","",#PB_Program_Open)
          If r
            pr.l = ProgramID(r)
            SetGadgetText(B_Stop,"STOP"+Chr(#LF)+"("+Str(pr)+")")
          Else
            MessageRequester("Program not running","Program not running")
          EndIf
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure

ProcedureDLL GetProcessMemory(PID.l)
   Structure PROCESS_MEMORY_COUNTERS
      cb.l;DW
      PageFaultCount.l;DW
      PeakWorkingSetSize.l;SIZE_T
      WorkingSetSize.l;SIZE_T
      QuotaPeakPagedPoolUsage.l;SIZE_T
      QuotaPagedPoolUsage.l;SIZE_T
      QuotaPeakNonPagedPoolUsage.l;SIZE_T
      QuotaNonPagedPoolUsage.l;SIZE_T
      PagefileUsage.l;SIZE_T
      PeakPagefileUsage.l;SIZE_T
   EndStructure
   
   pmc.PROCESS_MEMORY_COUNTERS   
   hProcess.l  = OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ, #False, PID)
   
   Static *F.i
   
   If *F=0
      If OpenLibrary(0,"PSAPI.DLL")
         *F=GetFunction(0,"GetProcessMemoryInfo")
         If *F=0
            CloseLibrary(0)
            ProcedureReturn -1 ; erreur
         EndIf
      Else
         ProcedureReturn -1 ; erreur
      EndIf
   EndIf
   
   CallFunctionFast(*F,hProcess,@pmc,SizeOf(pmc))
   
   ProcedureReturn pmc\WorkingSetSize
   
 EndProcedure
 
 
InitWindow_0()
Repeat
  event = Window_0_Events(WaitWindowEvent(20))
  If r
    ;b = GetMemoryUsage(#False)
    b= GetProcessMemory(pr.l)
    text$ = FormatDate("%hh:%ii:%ss",Date())+" - Delta:"+Str(b-a)+" Bytes"
    AddGadgetItem(Editor_0,0, text$)
    Debug b-a
    a = b
    Delay(100)
  EndIf
Until event = #False

If r
  CloseProgram(r)
EndIf

CloseWindow(Window_0)
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par graph100 »

Golfy a écrit :De pire en pire... mais ça va finir par marcher :roll:
Je ne comprend pas pourquoi tu dis ça, la procédure fonctionne. il ne reste plus qu'à programmer le reste correctement :lol:

J'ai repris un peu ton code, mais je l'ai mis à mes standard :roll: , question de lisibilité, de clarté de programmation, et surtout il n'y à pas de soucis de gestion d'event.

Il te reste à programmer le dessin du graph sur le canvas (je trouve le canvas bien mieux approprié que l'image gadget).
J'ai dans mes code un graph gadget, mais il dépend de mon environnement custom gadget, donc c'est un peu lourd de poster le code ici...

Code : Tout sélectionner

;{ structure et procedure

Structure PROCESS_MEMORY_COUNTERS
	cb.l;DW
	PageFaultCount.l;DW
	PeakWorkingSetSize.l;SIZE_T
	WorkingSetSize.l;SIZE_T
	QuotaPeakPagedPoolUsage.l;SIZE_T
	QuotaPagedPoolUsage.l;SIZE_T
	QuotaPeakNonPagedPoolUsage.l;SIZE_T
	QuotaNonPagedPoolUsage.l;SIZE_T
	PagefileUsage.l;SIZE_T
	PeakPagefileUsage.l;SIZE_T
EndStructure

ProcedureDLL GetProcessMemory(PID.l)
	Protected pmc.PROCESS_MEMORY_COUNTERS, hProcess.l
	hProcess.l = OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ, #False, PID)
	
	Static *F.i
	
	If *F = 0
		If OpenLibrary(0,"PSAPI.DLL")
			*F = GetFunction(0,"GetProcessMemoryInfo")
			If *F = 0
				CloseLibrary(0)
				ProcedureReturn -1 ; erreur
			EndIf
		Else
			ProcedureReturn -1 ; erreur
		EndIf
	EndIf
	
	CallFunctionFast(*F, hProcess, @pmc, SizeOf(pmc))
	
	ProcedureReturn pmc\WorkingSetSize
EndProcedure


;}

;{ init window

CMEM_window = OpenWindow(#PB_Any, 0, 0, 600, 270, "PB Leak Finder", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
Image_0 = CanvasGadget(#PB_Any, 10, 110, 580, 130)
CMEM_Button_exe = ButtonGadget(#PB_Any, 10, 10, 100, 20, "Choose EXE...")
CMEM_Button_quit = ButtonGadget(#PB_Any, 10, 70, 100, 20, "Quit", #PB_Button_Default)
CMEM_Button_stop = ButtonGadget(#PB_Any, 120, 10, 50, 50, "STOP",#PB_Button_MultiLine)
TextGadget(#PB_Any, 410, 13, 70, 20, "Check every")
TextGadget(#PB_Any, 570, 13, 20, 20, "sec.")
CMEM_combo = ComboBoxGadget(#PB_Any, 490, 10, 70, 20)
CMEM_checkbox_null = CheckBoxGadget(#PB_Any, 410, 35, 200, 20, "Only log memory event")
CMEM_Button_log = ButtonGadget(#PB_Any, 10, 40, 100, 20, "Please log-it", #PB_Button_Right | #PB_Button_Toggle)
CMEM_Button_aide = ButtonGadget(#PB_Any, 120, 70, 50, 20, "?")
CMEM_editor = EditorGadget(#PB_Any, 180, 10, 220, 80)

;{ remplissage de la combo

AddGadgetItem(CMEM_combo, -1, "0.1")
AddGadgetItem(CMEM_combo, -1, "0.2")
AddGadgetItem(CMEM_combo, -1, "0.5")
AddGadgetItem(CMEM_combo, -1, "1")
AddGadgetItem(CMEM_combo, -1, "2")
AddGadgetItem(CMEM_combo, -1, "5")

SetGadgetState(CMEM_combo, 2)
SetGadgetState(CMEM_checkbox_null, #True)

;}

;}

CMEM_program$ = ""
CMEM_program_ID = 0
CMEM_program_PID = 0
CMEM_temps = 0
CMEM_delay = 0
CMEM_log_null_event = #True

Repeat
	event = WaitWindowEvent(20)
	
	;{ traitement des events
	If event = #PB_Event_Gadget
		Select EventGadget()
			Case CMEM_Button_aide
				
			Case CMEM_Button_exe
				CMEM_program$ = OpenFileRequester("Programme a tester (Leak Memory)","*.exe","EXE|*.exe",0)
				
				If CMEM_program$
					CMEM_program_ID = RunProgram(CMEM_program$,"","",#PB_Program_Open)
					CMEM_temps = ElapsedMilliseconds()
					
					cmem_delay = ValD(GetGadgetText(CMEM_combo))*1000
					
					If CMEM_program_ID
						CMEM_program_PID = ProgramID(CMEM_program_ID)
						
						SetGadgetText(CMEM_Button_stop, "STOP" + #CR$ + "(" + Str(CMEM_program_PID) + ")")
					Else
						MessageRequester("Program not running","Program" + #CR$ + CMEM_program$ + #CR$ + "is Not running")
					EndIf
				EndIf
				
			Case CMEM_Button_log
				
			Case CMEM_Button_quit
				event = #PB_Event_CloseWindow
				
			Case CMEM_Button_stop
				If CMEM_program_ID
					KillProgram(CMEM_program_ID)
					CloseProgram(CMEM_program_ID)
					CMEM_program_ID = 0
				EndIf
				SetGadgetText(CMEM_Button_stop, "STOP")
				
			Case CMEM_checkbox_null
				CMEM_log_null_event = GetGadgetState(CMEM_checkbox_null)
				
			Case CMEM_combo
				cmem_delay = ValD(GetGadgetText(CMEM_combo))*1000
				
		EndSelect
	EndIf
	;}
	
	;{ log de la memoire
	If CMEM_program_ID And ElapsedMilliseconds() - CMEM_temps >= CMEM_delay
		CMEM_temps = ElapsedMilliseconds()
		
		CMEM_utilisation_mem = GetProcessMemory(CMEM_program_PID)
		
		If (CMEM_log_null_event And CMEM_utilisation_mem - CMEM_utilisation_mem_old <> 0) Or Not CMEM_log_null_event
			CMEM_text$ = FormatDate("%hh:%ii:%ss",Date())+" - Delta:"+Str(CMEM_utilisation_mem - CMEM_utilisation_mem_old)+" Bytes"
			AddGadgetItem(CMEM_editor, 0, CMEM_text$)
		EndIf
		
		CMEM_utilisation_mem_old = CMEM_utilisation_mem
		
		If ProgramRunning(CMEM_program_ID) = 0
			CloseProgram(CMEM_program_ID)
			CMEM_program_ID = 0
			
			CMEM_text$ = FormatDate("%hh:%ii:%ss",Date())+" - Program was ended"
			AddGadgetItem(CMEM_editor, 0, CMEM_text$)
		EndIf
	EndIf
	;}
	
Until event = #PB_Event_CloseWindow

;{ on arrête tout proprement

If CMEM_program_ID
	KillProgram(CMEM_program_ID)
	CloseProgram(CMEM_program_ID)
EndIf

;}

End

_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: comment débuguer des fuites de mémoire (memory leak) ?

Message par graph100 »

Voila un zip avec les codes du graphique. J'ai fait un exe au cas ou.
Memory Leak.zip
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Répondre