ScreenShot, fuite de mémoire (FreeImage) [Résolu]

Signaler
Messages postés
43
Date d'inscription
mercredi 30 novembre 2005
Statut
Membre
Dernière intervention
5 décembre 2008
-
Messages postés
43
Date d'inscription
mercredi 30 novembre 2005
Statut
Membre
Dernière intervention
5 décembre 2008
-
Bonsoir, ou bonjour à tous...
Cette nuit, un problème m'empêche de trouver le sommeil. Il s'agit d'un petit bout de code destiné à prendre un screenshot et à l'enregistrer au format jpg sur le disque grace à la lib FreeImage.
Le code fonctionne trés bien (il vient d'ailleur d'une source du site) mais pour les besoins de mon programme je dois boucler l'opération indéfiniment. Et là aprés 10 secondes de while(1), le programme gonfle en ram pour arriver à dépasser le Go et finir par occuper toute la mémoire... Je libère pourtant la mémoire au niveau des HDC, HBITMAP et variables FreeImage mais le problème persiste.
Je ne connais pas bien le principe des DC win32, etc.. C'est sans doute une erreur bête, mais je ne vois pas...
Si vous voulez jeter un oeil au vilain code...
merci d'avance.

PS : pour transformer un HBITMAP en variable FreeImage (FIBITMAP), je me suis servi de cet exemple que j'ai épurer (peut être trop!) 

http://freeimage.sourceforge.net/faq.html





#include <windows.h>
#include "FreeImage.h"




void takeScreenShot(const char *path)
{               
   // Récupération des dimensions du bureau :
   int ScreenX = GetSystemMetrics(SM_CXSCREEN);
   int   ScreenY = GetSystemMetrics(SM_CYSCREEN);
     
   // Récupération du HWND et du HDC du bureau :
   HWND hWndWindow = GetDesktopWindow();
   HDC hDcWindow = GetWindowDC(hWndWindow);
     
   // Récupération du nombre de couleurs :
   int nColors = GetDeviceCaps(hDcWindow, BITSPIXEL);
  
   // Création d'un contexte mémoire
   HDC   m_hDcBitmap = CreateCompatibleDC(hDcWindow);
  
   // On crée un bitmap en mémoire ayant les dimensions du bureau
   HBITMAP hbmp = CreateCompatibleBitmap(hDcWindow, ScreenX, ScreenY);
  
   // On sélectionne ce bitmap dans le contexte mémoire :
   SelectObject(m_hDcBitmap, hbmp);
  
   // copie du contexte écran vers le contexte mémoire :
   BitBlt(m_hDcBitmap, 0, 0, ScreenX, ScreenY, hDcWindow, 0, 0, SRCCOPY);
  
   DeleteDC(hDcWindow);

  
// Initialisation du FIBITMAP :



FreeImage_Initialise( true ); 
                 
FIBITMAP *dib = FreeImage_Allocate(ScreenX, ScreenY, nColors);



  
   // Copie du Hbitmap dans FIBITMAP : 
 
  GetDIBits(m_hDcBitmap, hbmp, 0, ScreenY ,FreeImage_GetBits(dib), FreeImage_GetInfo(dib), DIB_RGB_COLORS);



   DeleteObject(hbmp);
   DeleteDC(m_hDcBitmap);



  
   // conversion 24 (ou 8 Grayscale) obligatoire pour conversion JPEG
   dib = FreeImage_ConvertTo24Bits(dib);
  
   FreeImage_Save(FIF_JPEG, dib, path, 75);
  
   FreeImage_Unload(dib);
   FreeImage_DeInitialise();  
}




int main()
{
  while (1)takeScreenShot("test.jpg");
  return 0;
}

5 réponses

Messages postés
43
Date d'inscription
mercredi 30 novembre 2005
Statut
Membre
Dernière intervention
5 décembre 2008

Merci à tous pour vos réponses, j'ai fini par trouver l'erreur, elle vient de la ligne:



dib = FreeImage_ConvertTo24Bits(dib);


En fait FreeImage alloue un nouvel espace memoire pour l'image pointée par dib converti en 24bits. Vu que j'assigne le pointeur dib à cette dernière, l'ancien espace mémoire contenant l'image non convertie se retrouve sans rien pointant dessus et n'est donc pas libéré à l'apel de : FreeImage_Unload(dib);

Merci encore à bientôt.
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
15
Ce n'est peut-être pas la source du problème mais ce n'est pas DeleteDC que l'on appel suite à un GetWindowDC. C'est ReleaseDC.

C++ (@++)<!--
Messages postés
43
Date d'inscription
mercredi 30 novembre 2005
Statut
Membre
Dernière intervention
5 décembre 2008

Merci de ta contribution mais ce n'est malheureusement pas ça :
j'ai remplacé


DeleteDC(hDcWindow) par
ReleaseDC(hWndWindow,hDcWindow

)  mais le problème persiste.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
14
Salut,


Tu peux essayer de mettre en commentaire des bouts de codes pour cerner le problème.


Tu peux aussi essayer de modifier ton code de manière à n'effectuer des
allocation qu'au lancement du programme. Pas la peine de tout recréer à
chaque fois... sauf si tu veux gérer les changement de résolution de
l'écran / et ou les couleurs. Mais à ce moment là, il serait plus
judicieux de tout réallouer si et seulement si la configuration de
l'écran à changé.


M'enfin il serait préférable de régler ce problème de fuite avant de changer la structure de ton appli.
<hr size="2" width="100%" />3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
Messages postés
1100
Date d'inscription
jeudi 24 avril 2003
Statut
Membre
Dernière intervention
17 octobre 2012
6
Bonjour,

Essaye de le lancer en mode débug.
Sous Dev-C++ il te dit la ligne où il a planté.

Merci et bonne prog,
@++

Le créateur du site http://victorlogiciels.com