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

 Delphi Discussion :

Fuite mémoire dans une fonction


Sujet :

Delphi

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 74
    Par défaut Fuite mémoire dans une fonction
    Bonjour à tous

    j'ai une fuite mémoire dans ma fonction ci-dessous.
    merci de votre aide.


    Fonction de redimention du jpg
    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
     
    function TForm1.RedimentionJpg(ImgSrcJPG : TJpegImage; Taille : integer) : TJpegImage;
    var
      vImgBMP : TBitmap;
    begin
     
      vImgBMP := TBitmap.Create;
      Result  := TJpegImage.Create;
      try
        vImgBMP.Height:= Taille;
        vImgBMP.Width := Taille;
        vImgBMP.Canvas.StretchDraw(vImgBMP.Canvas.Cliprect, ImgSrcJPG);
        Result.Assign(vImgBMP);
      finally
        vImgBMP.Free;
      end;
    end;

    J'utilise ce code pour appeler la fonction.
    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
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      imgJPEG:TJPEGImage;
    begin
      { charger image et puis la reduire sa taille et la mettre  et afficher}
      if OpenPictureDialog1.Execute then
      begin
        imgJPEG:= TJPEGImage.Create;
        try
          imgJPEG.LoadFromFile(OpenPictureDialog1.FileName);
          image1.Picture.Assign(RedimentionJpg(imgJPEG,200)) ;
        finally
         imgJPEG.Free;
        end;
     
        //FParams.Change:= True;
      end;

  2. #2
    Membre Expert
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 400
    Par défaut
    Salut;

    désolé pour ma question, stupide, mais comment as-tu su que tu as une fuite mémoire ? et quelles sont les valeurs si tu en as ?

  3. #3
    Membre Expert
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 288
    Par défaut
    Salut,

    Lu en travers, mais en "RedimentionJpg", tu as deux Creates et... UN seul free

    @+

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 130
    Par défaut
    Faut libérer le paramètre en retour de RedimentionJpg
    le Assign fait une "copie" de l'objet et dans l'objet copié peut être libéré en toute sécurité
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 74
    Par défaut
    Just-Soft.

    Dans ma fiche utilise ce code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    System.ReportMemoryLeaksOnShutdown := True

    Droïde Système7
    Merci de ta réponse, mais si je fais un free sur result j'ai une violation d'accès.
    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
     
    function TForm1.RedimentionJpg(ImgSrcJPG : TJpegImage; Taille : integer) : TJpegImage;
    var
      vImgBMP : TBitmap;
    begin
     
      vImgBMP := TBitmap.Create;
      Result  := TJpegImage.Create;
      try
        vImgBMP.Height:= Taille;
        vImgBMP.Width := Taille;
        vImgBMP.Canvas.StretchDraw(vImgBMP.Canvas.Cliprect, ImgSrcJPG);
        Result.Assign(vImgBMP);
      finally
        vImgBMP.Free;
        Result.Free;  // violation 
      end;
    end;

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 130
    Par défaut
    J'étais sur qu'avec la remarque de Droïde Système7, qu'un débutant tomberait dans le piège de libérer son résultat ... MedKyl essaye de comprendre ce que tu fais avant de poster, si DS7 te demande de te jeter du Pont, tu sautes ?

    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
    procedure TForm1.Button1Click(Sender: TObject);
    var
      imgJPEG:TJPEGImage;
      imgJPEG200: TJpegImage;
    begin
      { charger image et puis la reduire sa taille et la mettre  et afficher}
      if OpenPictureDialog1.Execute then
      begin
        imgJPEG:= TJPEGImage.Create;
        try
          imgJPEG.LoadFromFile(OpenPictureDialog1.FileName);
          imgJPEG200 := RedimentionJpg(imgJPEG,200);
          try 
            image1.Picture.Assign(imgJPEG200 ) ;
          finally
            imgJPEG200.Free;
          end;
        finally
         imgJPEG.Free;
        end;
     
        //FParams.Change:= True;
      end;
    PS : Supprime le "Result.Free;" évidemment
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre Expert
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Par défaut
    permet de redimensionner JPEG/PNG/GIF/TIF/BMP etc.

    attention consomme de la mémoire.

    exemple consomation :
    image bitmap 2000x2000x32b (16Mo) vers bitmap 1000x1000x32b (4Mo) =

    avant appel : 16Mo
    process en cours : 40Mo
    aprés process : 20Mo

    utilisation :

    RedimPic(P1, P2, 640, 0) -> redimensionne par Width en gardant le ratio WH
    RedimPic(P1, P2, 0, 600) -> redimensionne par Height en gardant le ratio WH
    RedimPic(P1, P2, 640, 480) -> redimensionne par Width et Height sans garder le ratio.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RedimPic(Bitmap1, JPEG1, 320, 0);
    redimensionne Bitmap1 dans JPEG1 avec une longueur de 320 pixels en gardant le ratio WH.
    si Bitmap1 = 800x600
    R = 320/800 = 0.4 (40% de longueur initiale)
    W = 800 * 0.4 = 320
    H = 600 * 0.4 = 240


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RedimPic(JPEG1, JPEG2, 0, 768);
    redimensionne JPEG1 dans JPEG2 avec une hauteur de 768 en gardant le ratio WH.
    si JPEG1 = 1280x1024
    R = 768/1024 = 0.75 (75% de hauteur initiale)
    W = 1280 * 0.75 = 960
    H = 1024 * 0.75 = 768


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RedimPic(BMP1, BMP1, BMP1.Width shr 1, BMP1.Height shr 1);
    redimensionne BMP1 lui même avec une taille 50% plus petite (shr 1 = div 2 = 50%)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    JPG.LoadFromFile('MonJpg.jpg');
     
    JPG.DIBNeeded; 
     
    if JPG.Width > JPG.Height then
      RedimPic(JPG, JPG, 96, 0)
    else
      RedimPic(JPG, JPG, 0, 96);
     
    JPG.JPEGNeeded;
    JPG.CompressionQuality := 75;
    JPG.Compress;
     
    JPG.SaveToFile('MonJpg.Thumb.jpg');
    crée un aperçus au maximum 96x96 à partir d'un JPEG.




    la fonction RedimPic et ses constantes d'erreur
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    {$DEFINE RPICASSERT}
     
    const
      RPIC_SUCCESS        = 0;
      RPIC_NODIMENSION    = 1;
      RPIC_SRCNOTASSIGNED = 2;
      RPIC_DSTNOTASSIGNED = 3;
      RPIC_SRCEMPTY       = 4;
      RPIC_BUFFERERROR    = 5;
      RPIC_STRETCHERROR   = 6;
      RPIC_DESTOUTERROR   = 7;
     
    function RedimPic(Src, Dest: TGraphic; const NewWidth, NewHeight: LongInt): LongInt;
    var NW, NH : LongInt;
        R : Single;
        BufferDest, BufferSrc : TBitmap;
    begin
      result := RPIC_NODIMENSION;
      {$IFDEF RPICASSERT}
      assert((NewWidth > 0) or (NewHeight > 0), 'Vous n''avez pas precisé de nouvelle dimensions pour l''image !');
      {$ELSE}
      if (NewWidth <= 0) and (NewHeight <= 0) then
        exit;
      {$ENDIF}
     
      result := RPIC_SRCNOTASSIGNED;
      {$IFDEF RPICASSERT}
      assert(assigned(Src), 'Image source non assignée !');
      {$ELSE}
      if not assigned(Src) then
        exit;
      {$ENDIF}
     
      result := RPIC_DSTNOTASSIGNED;
      {$IFDEF RPICASSERT}
      assert(assigned(Dest), 'Image de destination non assignée !');
      {$ELSE}
      if not assigned(Dest) then
        exit;
      {$ENDIF}
     
      result := RPIC_SRCEMPTY;
      {$IFDEF RPICASSERT}
      assert(not Src.Empty, 'Image source est vide !');
      {$ELSE}
      if Src.Empty then
        exit;
      {$ENDIF}
     
      if (NewWidth > 0) and (NewHeight > 0) then
      begin
        NW := NewWidth;
        NH := NewHeight;
      end
      else
      if NewWidth > 0 then
      begin
        R  := 1 - NewWidth / Src.Width;
        NW := trunc(Src.Width * R);
        NH := trunc(Src.Height * R);
      end
      else
      if NewHeight > 0 then
      begin
        R  := 1 - NewHeight / Src.Height;
        NW := trunc(Src.Width * R);
        NH := trunc(Src.Height * R);
      end;
     
      result := RPIC_BUFFERERROR;
      BufferDest := TBitmap.Create;
      BufferSrc := TBitmap.Create;
      try
        BufferSrc.Width := Src.Width;
        BufferSrc.Height := Src.Height;
        BufferSrc.Canvas.Draw(0, 0, Src);
     
        BufferDest.Width := NW;
        BufferDest.Height := NH;
     
        result := RPIC_STRETCHERROR;
        SetStretchBltMode(BufferDest.Canvas.Handle, HALFTONE);
        StretchBlt(BufferDest.Canvas.Handle, 0, 0, NW, NH,
                   BufferSrc.Canvas.Handle, 0, 0, BufferSrc.Width, BufferSrc.Height,
                   SRCCOPY);
     
        result := RPIC_DESTOUTERROR;
        Dest.Assign(BufferDest);
     
      finally
        result := RPIC_BUFFERERROR;
        BufferSrc.Free;
        BufferDest.Free;
      end;
     
      result := RPIC_SUCCESS;
    end;
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 74
    Par défaut
    Merci à tous pour votre aide.
    ShaiLeTroll
    j'ai déjà sauté d'un pont mais avec un élastique.
    en faite je voulais passer par une fonction car pleins de traitements à faire.
    Dr.Who
    Merci c'est tout à fait ce que je recherchai.

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

Discussions similaires

  1. Problème de libération de la mémoire dans une fonction
    Par ArnaudFu1 dans le forum Débuter
    Réponses: 2
    Dernier message: 23/02/2012, 17h21
  2. Fuites mémoire dans une classe "java.util.HashMap$Entry"
    Par ladyingold dans le forum Collection et Stream
    Réponses: 19
    Dernier message: 10/02/2012, 16h51
  3. (Re)Allocation dynamique de mémoire dans une fonction
    Par Stupendous Man dans le forum Débuter
    Réponses: 11
    Dernier message: 17/06/2011, 17h46
  4. Fuite mémoire dans une appli dev avec vc++6
    Par devconf77 dans le forum Windows
    Réponses: 1
    Dernier message: 26/08/2008, 09h58

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