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 :

Problème memory leak


Sujet :

Delphi

  1. #1
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut Problème memory leak
    Bonjour,

    j'ai des problèmes de memory leak après activation de sharemem.

    Au début, le code qui pose problème était le suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function TCompoCustom.TBitmapToTGPBitmap(DBitmap:TBitmap):TGPBitmap;
    var
      stream:TMemoryStream;
    begin
     
      stream := TMemoryStream.Create;
      DBitmap.SaveToStream(stream);
      Result := TGPBitmap.Create(TStreamAdapter.Create(stream));
     
    end;
    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
    TCompoCustom.paint;
    var
      OGraphics:TGPGraphics;
      tampon:TBitmap;
     
    begin
    tampon:=nil;
    ..........
    tampon:=TBItmap.create();
    OGraphics:=TGPGraphics.Create(Canvas.Handle);
    OGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
    OGraphics.SetCompositingQuality(QualityModeHigh);
    OGraphics.DrawImage(TBitmapToTGPBitmap(tampon),0,0);
     
    try if tampon<>nil then FreeAndNil(tampon); except end;
    try FreeAndNil(OGraphics); except end;
    Ce code générait des memory leak, je l'ai donc modifié comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function TCompoCustom.TBitmapToTGPBitmap(DBitmap:TBitmap;stream:TMemoryStream;StreamAdapter:TStreamAdapter):TGPBitmap;
     
    begin
     
      stream := TMemoryStream.Create;
      DBitmap.SaveToStream(stream);
      StreamAdapter:=TStreamAdapter.Create(stream)
      Result := TGPBitmap.Create(StreamAdapter);
     
    end;
    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
    TCompoCustom.paint;
    var
      OGraphics:TGPGraphics;
      stream:TMemoryStream;
      StreamAdapter:TStreamAdapter
      tampon:TBitmap;
    begin
    tampon:=nil;
    ..........
    tampon:=TBitmap.create();
    OGraphics:=TGPGraphics.Create(Canvas.Handle);
    OGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
    OGraphics.SetCompositingQuality(QualityModeHigh);
    OGraphics.DrawImage(TBitmapToTGPBitmap(tampon,stream,StreamAdapter),0,0);
     
    try if tampon<>nil then FreeAndNil(tampon); except end;
    try FreeAndNil(stream); except end;
    try FreeAndNil(StreamAdapter); except end;
    try FreeAndNil(OGraphics); except end;
    Et la toujours un problème de leak....

    Je ne comprend pas, car même si ca parait un peu bancal de déclarer des var dans un pâint pour les allouer dynamiquement dans une fonction, les variables sont bien libérées....

    Quelqu'un pourrait t'il me mettre sur la voie svp, il semblerait que quelque chose m'échappe dans la gestion de la mémoire
    Merci

  2. #2
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 290
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 290
    Points : 1 941
    Points
    1 941
    Par défaut
    L'objet retourné par TBitmapToTGPBitmap n'est jamais liberé.

  3. #3
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    oui tu as raison, j'ai oublié de préciser que j'avais aussi testé ca.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tampon2:=TBitmapToTGPBitmap(tampon,stream,StreamAdapter);
    ...........
    FreeAndNil(tampon2);
    ca me sort une erreur également, qui viendrait de la libération apparement...

  4. #4
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 290
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 290
    Points : 1 941
    Points
    1 941
    Par défaut
    Dans ton code, il manque la déclaration et la création de tampon, mais je ne pense pas que ça vienne de là.

    Par contre les try except sur les destructeurs sont inutiles. Si tu as des exceptions dessus, c'est qu'il y a un autre problème.

    Par contre au niveau logique de programmation, je ferais plus:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    function TCompoCustom.TBitmapToTGPBitmap(DBitmap:TBitmap):TGPBitmap;  
    var
      StreamAdapter:TStreamAdapter;
      Stream:TMemoryStream;
    begin 
      Stream := TMemoryStream.Create;
      DBitmap.SaveToStream(Stream);
      StreamAdapter:=TStreamAdapter.Create(Stream)
      Result := TGPBitmap.Create(StreamAdapter);
      StreamAdapter.Free;
      Stream.Free;
    end;
    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
     
    TCompoCustom.paint;
    var
      OGraphics:TGPGraphics;
    GPBitmap:TGPBitmap;
    begin
    tampon:=nil;
    ..........
    OGraphics:=TGPGraphics.Create(Canvas.Handle);
    OGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
    OGraphics.SetCompositingQuality(QualityModeHigh);
    GPBitmap := TBitmapToTGPBitmap(tampon);
    OGraphics.DrawImage(GPBitmap,0,0);
    GPBitmap.Free;
     
    if Assigned(nil) then FreeAndNil(tampon);
    FreeAndNil(OGraphics);

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 71
    Points : 102
    Points
    102
    Par défaut
    Salut,
    Moi ce qui me dérange c'est Tampon := nil...
    Quand tu fais un FreeAndNil(Tampon)...ben en fait il se passe rien, pas de handle pour le FreeAndNil...
    C'est peut-être ceci que tu devrais utiliser Tampon.FreeImage;
    @+

  6. #6
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    Dans ton code, il manque la déclaration et la création de tampon, mais je ne pense pas que ça vienne de là.
    Lol effectivement le tampon est bien crée dans le paint, c'était un oubli de ma part dans le topic.

  7. #7
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function TCompoCustom.TBitmapToTGPBitmap(DBitmap:TBitmap):TGPBitmap;  
    var
      StreamAdapter:TStreamAdapter;
      Stream:TMemoryStream;
    begin 
      Stream := TMemoryStream.Create;
      DBitmap.SaveToStream(Stream);
      StreamAdapter:=TStreamAdapter.Create(Stream)
      Result := TGPBitmap.Create(StreamAdapter);
      StreamAdapter.Free;
      Stream.Free;
    end;
    J'ai bien essayé comme ça mais les deux derniers lignes de cette fonction me font une erreur invalid pointer exception...

  8. #8
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    Salut,
    Moi ce qui me dérange c'est Tampon := nil...
    Quand tu fais un FreeAndNil(Tampon)...ben en fait il se passe rien, pas de handle pour le FreeAndNil...
    C'est peut-être ceci que tu devrais utiliser Tampon.FreeImage;
    j'ai oublié de mettre la partie création.
    Je le met à nil au tout début pour pas le libérer si ca la pas créer, au cas ou!

    FreeAndNil(tampon) ne libère pas l'image du tampon? A mon avis si! non?

  9. #9
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    Quand je met juste Stream.Free;, j'ai une erreur :

    FASTMM has detected an attempt to call a virtual method on a freed object. AN acces violation will nos be raied in order to abort the current operation

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 71
    Points : 102
    Points
    102
    Par défaut
    aarrrhh...
    en fait ce que je veux dire c'est que j'espère tu fait pas ce genre de truc
    en conception, libération...en gros un exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Tampon := TBitmap.Create;
    try
        Tampon := nil;
    finally
        Tampon.Free;
    end;
    ici pas d'erreur sauf que si tu regarde avec ReportMemoryLeaksOnShutdown
    ton tampon n'est jamais libèrer...
    @+

  11. #11
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    Non je fais ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Tampon := nil;
    try
       Tampon := TBitmap.Create; 
    finally
        if tampon<>nil then FreeAndNil(Tampon);
    end;

  12. #12
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    En fait j'ai deux fonctions :

    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
    //GDI+
    function TCustomCompo.TPNGImagetoTGPBitmap(Dimage:TPNGImage):TGPBitmap;
    var
      stream:TMemoryStream;
      streamadapter:TStreamAdapter;
    begin
      stream := TMemoryStream.Create;
      Dimage.SaveToStream(stream);
      streamadapter:= TStreamAdapter.Create(stream);
      Result := TGPBitmap.Create(streamadapter);
      try FreeAndNil(Stream); except end;
      end;
     
    function TCustomCompo.TBitmapToTGPBitmap(DBitmap:TBitmap):TGPBitmap;
    var
      stream:TMemoryStream;
      streamadapter:TStreamAdapter;
    begin
     
      stream := TMemoryStream.Create;
      DBitmap.SaveToStream(stream);
      streamadapter:= TStreamAdapter.Create(stream);
      Result := TGPBitmap.Create(streamadapter);
      try FreeAndNil(Stream); except end;
    end;
    Déja, si j'essaye de libérer le streamadapter, ca plante, selon ce que j'ai lu il n'y aurait pas besoin de le libérer, il faut juste qu'il n'y ait plus de références dessus pour qu'il se libère (cf java.....et ses prises de têtes!).

    Par contre, pour le memorystream, dans la premiere fonction, la libération marche bien et en effet enleve du leak.
    Dans la seconde fonction, cela me leve une erreur FastMM comme décrit précédement.

    Je ne comprend pas pourquoi

  13. #13
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 290
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 290
    Points : 1 941
    Points
    1 941
    Par défaut
    Tu ne dois pas avoir de try except sur un destructor.
    Si ton destructor lève une exception, il y a un problème. C'est de ce côté là qu'il faut chercher.

    Par contre je ne peux pas t'aider je ne connais pas les composants prodigy (de ce que 'jai compris).

  14. #14
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut
    j'ai résolu le problème en changeant les fonctions, c'est moins joli mais au moins ça leake plus...

    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
    procedure TCustomCompo.DrawPNGImageGDIplus(DOGraphics:TGPGraphics;Dimage:TPNGImage;DLeft,DTop,DWidth,DHeight:integer);
    var
      stream:TMemoryStream;
      streamadapter:TStreamAdapter;
      GP:TGPBitmap;
      img_thumbnail:TGPImage;
    begin
      stream := TMemoryStream.Create;
      Dimage.SaveToStream(stream);
      streamadapter:= TStreamAdapter.Create(stream);
      GP := TGPBitmap.Create(streamadapter);
     
      img_thumbnail:=GP.GetThumbnailImage(DWidth,DHeight,nil,nil);
      DOGraphics.DrawImage(img_thumbnail,DLeft,DTop);
      try FreeAndNil(Stream); except end;
      try FreeAndNil(GP); except end;
      try FreeAndNil(img_thumbnail); except end;
     
    end;
    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
    procedure TCustomCompo.DrawBitmapGDIplus(DBitmap:TBitmap;DLeft,DTop:integer);
    var
      stream:TMemoryStream;
      streamadapter:TStreamAdapter;
      OGraphics:TGPGraphics;
      GP:TGPBitmap;
    begin
     
      stream := TMemoryStream.Create;
      DBitmap.SaveToStream(stream);
      streamadapter:= TStreamAdapter.Create(stream);
      GP := TGPBitmap.Create(streamadapter);
      OGraphics:=TGPGraphics.Create(Canvas.Handle);
      OGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
      OGraphics.SetCompositingQuality(QualityModeHigh);
      OGraphics.DrawImage(GP,DLeft,DTop);
     
      try FreeAndNil(Stream); except end;
      try FreeAndNil(GP); except end;
      try FreeAndNil(OGraphics); except end;
      //try FreeAndNil(streamadapter); except end;
    end;
    Voila si ca peut aider quelqu'un.
    Merci de votre aide

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

Discussions similaires

  1. Problème de memory leaks
    Par FourierFan dans le forum wxWidgets
    Réponses: 2
    Dernier message: 19/06/2008, 11h17
  2. Problème de memory leak
    Par Tiberizz dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 19/05/2007, 17h11
  3. Memory leak en C/C++
    Par Roswell dans le forum Autres éditeurs
    Réponses: 6
    Dernier message: 07/07/2004, 19h41
  4. [MFC] A la chasse au memory leak
    Par Yabo dans le forum MFC
    Réponses: 17
    Dernier message: 27/06/2004, 17h35
  5. Réponses: 7
    Dernier message: 26/02/2004, 09h32

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