ScreenShot, fuite de mémoire (FreeImage)

Résolu
ssmint Messages postés 43 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 5 décembre 2008 - 21 nov. 2007 à 05:05
ssmint Messages postés 43 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 5 décembre 2008 - 23 nov. 2007 à 12:00
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

ssmint Messages postés 43 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 5 décembre 2008
23 nov. 2007 à 12:00
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.
3
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
21 nov. 2007 à 05:19
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++ (@++)<!--
0
ssmint Messages postés 43 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 5 décembre 2008
21 nov. 2007 à 13:48
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.
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
21 nov. 2007 à 18:06
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
victorcoasne Messages postés 1101 Date d'inscription jeudi 24 avril 2003 Statut Membre Dernière intervention 23 juillet 2023 7
22 nov. 2007 à 22:05
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
0
Rejoignez-nous