IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

[Windows] Libération de la mémoire


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Par défaut [Windows] Libération de la mémoire
    Bonjour,

    J'ai une fuite mémoire lorsque je lance cette fonction en boucle.
    Apparement le "GlobalFree(BmpFileData);" ne suffit pas, que faut-il libérer et comment ?
    Merci pour votre aide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    void ScreenShot(char*BmpName, int x, int y, int w, int h, int full)
    {
    	HWND DesktopHwnd = GetDesktopWindow();
    	RECT DesktopParams;
    	HDC DevC = GetDC(DesktopHwnd);
    	GetWindowRect(DesktopHwnd,&DesktopParams);
     
    	DWORD Width = w;
    	DWORD Height = h;
    	if(full)
    	{
    	    x=0;
    	    y=0;
    	    Width = DesktopParams.right - DesktopParams.left;
            Height = DesktopParams.bottom - DesktopParams.top;
    	}
     
    	DWORD FileSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBTRIPLE)+1*(Width*Height*4));
    	char *BmpFileData = (char*)GlobalAlloc(0x0040,FileSize);
     
    	PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
    	PBITMAPINFOHEADER  BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];
     
    	BFileHeader->bfType = 0x4D42; // BM
    	BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
    	BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
     
    	BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
    	BInfoHeader->biPlanes = 1;
    	BInfoHeader->biBitCount = 24;
    	BInfoHeader->biCompression = BI_RGB;
    	BInfoHeader->biHeight = Height;
    	BInfoHeader->biWidth = Width;
     
    	RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
    	//RGBTRIPLE color;
     
    	HDC CaptureDC = CreateCompatibleDC(DevC);
    	HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC,Width,Height);
    	SelectObject(CaptureDC,CaptureBitmap);
    	BitBlt(CaptureDC,0,0,Width,Height,DevC,x,y,SRCCOPY|CAPTUREBLT);
    	GetDIBits(CaptureDC,CaptureBitmap,0,Height,Image,(LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
     
    	DWORD Junk;
    	HANDLE FH = CreateFileA(BmpName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
    	WriteFile(FH,BmpFileData,FileSize,&Junk,0);
    	CloseHandle(FH);
        GlobalFree(BmpFileData);
    }

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par nanosoft Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	char *BmpFileData = (char*)GlobalAlloc(0x0040,FileSize);
        GlobalFree(BmpFileData);
    }
    Bonjour

    D'après cette page, le GlobalAlloc retourne un PSECURITY_DESCRIPTOR. Et c'est ce type qui est envoyé à GlobalFree.

    Toi, tu castes son retour en char* et c'est ce char* que tu envoies à GlobalFree. Je présumerai donc que GlobalFree ne reçoit pas tout ce dont il a besoin.

    Imaginons par exemple que le PSECURITY_DESCRIPTOR soit un pointeur complexe (comme l'est par exemple le date_t ou le FILE *) avec la fonction GlobalAlloc renvoyant une adresse sur cette structure. En le récupérant dans un type adéquat tu protèges l'ensemble de la structure. Mais en le récupérant dans un char*, ben tu ne récupères que l'adresse des 8 premiers bits de la structure et le reste n'est plus protégé.
    Bon bref j'ai bien conscience en écrivant ceci que c'est assez bancal comme excuse (même en récupérant l'adresse d'une structure dans un char* on a quand-même la structure complète) mais c'est la seule chose que je vois...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    De mémoire, depuis Win32, on peut directement passer un pointeur à GlobalFree() comme tu l'as fait.
    Mais 3 gros objets ne sont pas libérés dans ton code.
    Il faut rendre le DC pris par GetDC() et faisant un ReleaseDC( DevC ); à la fin.
    Il faut détruire le memory DC créé par CreateCompatibleDC() en appelant DeleteObject() après avoir désélectionné la bitmap qu'il contient.
    Il faut aussi détruire la CaptureBitmap avec DeleteObject().
    Devrait se terminer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    HDC CaptureDC = CreateCompatibleDC(DevC);
    	HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC,Width,Height);
    	HBITMAP previousBM = (HBITMAP)SelectObject(CaptureDC,CaptureBitmap); // noter bitmap précédente
    	BitBlt(CaptureDC,0,0,Width,Height,DevC,x,y,SRCCOPY|CAPTUREBLT);
    	GetDIBits(CaptureDC,CaptureBitmap,0,Height,Image,(LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
     
    	DWORD Junk;
    	HANDLE FH = CreateFileA(BmpName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
    	WriteFile(FH,BmpFileData,FileSize,&Junk,0);
    	CloseHandle(FH);
        DeleteObject( SelectObject( CaptureDC, previousBM ) );  // remettre ancienne et détruire bitmap
        DeleteObject( CaptureDC ); // détruire memory DC
        ReleaseDC( DevC ); // rendre le DC
        GlobalFree(BmpFileData);

  4. #4
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Par défaut
    Merci dalfab pour cette expertise pertinente :
    Je n’ai plus cette (énorme en plein écran) fuite mémoire.
    Il manquait juste un paramètre pour ReleaseDC() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CloseHandle(FH);
    DeleteObject( SelectObject( CaptureDC, previousBM ) );  // remettre ancienne et détruire bitmap
    DeleteObject( CaptureDC );                              // détruire memory DC
    ReleaseDC(DesktopHwnd, DevC );                          // rendre le DC
    GlobalFree(BmpFileData);
    Je profite du post pour exposer un autre souci, structurel celui-là :
    Comme sur ma machine la fonction prend environ 70ms, j’utilise 4 threads entrelacés pour la faire tourner à 25Hz : cela se passe bien sauf que de temps en temps un thread dure 200 voire 600ms. Je suppose que c’est l’accès disque qui traîne à ce moment là ; je ne rate que 1% des images mais c’est ennuyeux pour la synchronisation.
    De toute manière je ne pourrais jamais paralléliser la sauvegarde disque qui dure d’après mes tests 20 à 30ms.
    J’envisage de couper la fonction en deux :
    - sauvegarde synchrone en mémoire (4 threads)
    - écriture asynchrone sur disque et libération (1 thread)

    Faire le transfert entre les 2 fonctions avec « BmpFileData » est-il une bonne solution ?

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Par défaut Ecriture sur disque
    J’ai séparé la fonction en deux et je stocke les BmpFileData en mémoire mais cela ne marche cependant que sur une durée limitée :
    La deuxième partie de la fonction (écriture disque et libération mémoire) présente au début un temps d’exécution de moins de 10ms mais celui-ci ne fait que s’allonger au fil du temps (jusqu’à 500ms) et il n’est plus possible de libérer assez vite les allocations même avec une pile énorme en mémoire.

    Y aurait-il une astuce pour écrire à la volée sur le disque ?
    Un autre mécanisme ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    void Mem2Disk(long int ind)
    {
        long int dep=SDL_GetTicks();
        char indice[10]="0";
        sprintf(indice,"%li.bmp",ind);
        DWORD Junk;
        char BmpName[MAX_PATH]={0};     // Nom du fichier .bmp
        strcpy(BmpName,repertoire);
        strcat(BmpName,"\\Images\\");
        strcat(BmpName,numCapt);        // n° Capture
        strcat(BmpName,"_");
        strcat(BmpName,indice);         // n° Image
    	HANDLE FH = CreateFileA(BmpName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
    	WriteFile(FH,BmpBuffer[ind],CapSize[ind],&Junk,0);     // Ecriture disque du Buffer mémoire
    	CloseHandle(FH);
        GlobalFree(BmpBuffer[ind]);                             // Libération Buffer
        long int fin1 = SDL_GetTicks();
        printf("Durée écriture disque %li : %li ms \n",ind, (fin1-dep));
    }

  6. #6
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Par défaut
    Bon, je passe le sujet en résolu :
    Plus de fuite mémoire, pour le reste le débit d'écriture est tout simplement trop élevé par rapport à la vitesse du disque dur.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Libération de la mémoire
    Par Premium dans le forum C
    Réponses: 4
    Dernier message: 09/08/2006, 18h15
  2. [CSV] Libération de la mémoire
    Par cedricgirard dans le forum Langage
    Réponses: 7
    Dernier message: 05/01/2006, 12h02
  3. libération de la mémoire après traitement ?
    Par isachat666 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 07/12/2005, 19h29
  4. [VB]Libération de la mémoire
    Par seroa dans le forum VB 6 et antérieur
    Réponses: 13
    Dernier message: 12/10/2005, 11h52
  5. Libération de la mémoire
    Par gibet_b dans le forum Composants VCL
    Réponses: 3
    Dernier message: 30/06/2004, 12h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo