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

Composants VCL Delphi Discussion :

Impression TPicture et fuite mémoire


Sujet :

Composants VCL Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 25
    Par défaut Impression TPicture et fuite mémoire
    Bonjour,

    J'ai réalisé un traitement pour imprimer des images. Les images sont relativement volumineuses et l'espace mémoire occupé par mon programme augmente constamment. Je n'arrive pas à comprendre comment cette fuite mémoire se produit. Elle se produit d'ailleurs de façon aléatoire.

    Voici le code permettant de dessiner l'image:
    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
    procedure DessineImage(Imprimante: TPrinter; x1, y1, x2, y2: Integer; str_imagePath: string);
    var
      rec_Cadre: TRect;
      picture: TPicture;
    begin
      picture := TPicture.Create;
      try
        picture.LoadFromFile(str_imagePath);
        rec_Cadre.Left := x1;
        rec_Cadre.Top := y1;
        rec_Cadre.Right := x2;
        rec_Cadre.Bottom := y2;
        Imprimante.Canvas.StretchDraw(rec_Cadre, picture.Graphic);
      finally
        picture.Free;
      end;
    end;
    Quand je débugge en pas à pas, je m'aperçois que l'application ne charge pas l'image en mémoire au moment du LoadFromFile, mais au moment du StrechDraw. L'image se charge d'ailleurs 2 fois en mémoire: dans le TPicture et dans le canvas de l'imprimante. Parfois le picture.Free, décharge sa mémoire, parfois pas. Au moment du Printer.NewPage, le canvas de l'imprimante se décharge bien.

    Résultat: mon programme qui prend 16Mo de mémoire du début du traitement peut en prendre 100 à la fin, et parfois 200, avec les mêmes images.

    L'aide la fonction Free du TPicture indique "Détruit un objet et libère si nécessaire la mémoire associée." Que signifie le "si nécessaire"?
    Que faut-il faire pour que la mémoire se libère correctement à tous les coups?

    ---
    J'ai oublié de préciser que je travaille avec Delphi 2007.

    Je viens de faire un test supplémentaire: faire du TPicture une variable globale et ne jamais faire de free. Le résultat est le même. Après l'impression des images, parfois la mémoire augmente, parfois pas.

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 941
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 941
    Par défaut
    Je me demande si c'est pas plutôt ce paramètre imprimante qui gène.
    Tu n'as de toute façon qu'un imprimante utilisable à la fois et on y accède simplement par Printer. Là, tu fais une copie locale de l'imprimante. Comment est-ce géré derrière, mystère

    Essaye comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure DessineImage(x1, y1, x2, y2: Integer; str_imagePath: string);
    var
      rec_Cadre: TRect;
      picture: TPicture;
    begin
      picture := TPicture.Create;
      try
        picture.LoadFromFile(str_imagePath);
        rec_Cadre := Rect(x1, y1, x2, y2);
        Printer.Canvas.StretchDraw(rec_Cadre, picture.Graphic);
      finally
        picture.Free;
      end;
    end;

  3. #3
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 25
    Par défaut
    Le code que tu proposes est exactement celui que j'avais avant et c'est pareil.

    J'ai fait cette modification car je voulais rendre le code plus générique et faire une DLL avec ces fonctions d'impression. Mais ce n'est pas le sujet qui m'intéresse présentement.

  4. #4
    Membre Expert
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Par défaut
    Tu peux utiliser des outils comme FastMM4 ou MemProof pour tenter de localiser l'origine des fuites mémoires...

  5. #5
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Par défaut
    Tu peux aussi utiliser la variable ReportMemoryLeaksOnShutdown à mettre à true pour indiquer les fuites mémoire ...
    Cette fonctionnalité est présente depuis Delphi 2006.

  6. #6
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 25
    Par défaut
    Merci à tous pour vos réponses.

    Je viens d'essayer certains de ces outils, je n'ai rien de probant. Des fuites sont bien détectées, mais elles représentent quelques kilos et non des mégas comme c'est le cas.

    De plus, la fuite est bien identifiée, il s'agit d'un problème sur la gestion du TPicture. Soit j'ai raté quelques chose dans l'utilisation du composant, soit il y a un bug, mais je ne suis pas assez compétent et motivé pour débugger le code des librairies Delphi.

    Peut-être quelqu'un a-t-il une autre solution pour intégrer un fichier JPG dans mon impression?

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 101
    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 101
    Par défaut
    Citation Envoyé par dwinkel Voir le message
    code plus générique et faire une DLL avec ces fonctions d'impression.
    Euh, mieux vaut passer le nom (obtenu via GetPrinter) via un PChar qu'un objet TPrinter dans une DLL (sauf si ShareMem ne te dérange pas), sinon, il existe aussi PrinterIndex qui te permet de sélectionner l'imprimante en cours ...

    Pour le JPEG, tu peux utiliser TJPEGImage directement comme objet TGraphic dans StretchDraw car TJPEGImage implémente la méthode protégée Draw introduite dans TGraphic. Cela signifie qu'il peut se dessiner lui-même sur le canevas d'un autre objet donc faire un StretchDraw

    C'est la méthode en D7 puis le TPicture ne gèrait pas le JPEG nativement !
    C'était l'unite "jpeg", j'ignore si cela existe encore en D2007
    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

  8. #8
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 25
    Par défaut
    Le composant TJPEGImage existe toujours. C'est une sous-classe de TGraphic.
    J'obtiens le même résultat.

    J'ai encore essayé de créer un TBitmap vide et de l'assigner au TJPEGImage. Cela ne change rien.

    En fait, j'avais oublié de préciser une chose, mais qui ne dois pas être déterminante: quand j'exécute l'application dans ma VM de développement ou sur le PC d'un utilisateur, le problème est beaucoup plus flagrant que si je l'exécute directement sur mon poste, qui est plus performant. Étonnant non?

  9. #9
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 101
    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 101
    Par défaut
    Tu imprimes dans un Fichier ou réellement ?
    Lors du EndDoc ou Abort, la mémoire de ne baisse pas ?

    Perso, j'ai déjà fait des impressions d'image (via StrechDraw) et de grille (via DrawTo) en D6, je n'ai eu aucun soucis de mémoire, pourtant les images était conséquente (JPEG issu de DICOM), du moins la mémoire revenait au même point entre le BeginDoc et EndDoc, je ne me suis jamais occupé de la mémoire entre les deux surtout avec des JPEG entre 3000 et 6000 dpi on sait déjà que les chiffres s'affolent ! Tant que l'avant-après est correct et que le client ne se plaint pas !
    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

Discussions similaires

  1. [tomcat][memoire] java.net.URL et fuite mémoire
    Par Seiya dans le forum Tomcat et TomEE
    Réponses: 6
    Dernier message: 09/03/2009, 10h41
  2. [Fuites mémoire] Je cherche un utilitaire
    Par 10_GOTO_10 dans le forum C++Builder
    Réponses: 8
    Dernier message: 10/02/2005, 10h03
  3. Outil de recherche de fuite mémoire
    Par eag35 dans le forum MFC
    Réponses: 4
    Dernier message: 02/02/2005, 12h46
  4. [SWT]SWT et fuite mémoire(ou pas)
    Par menuge dans le forum SWT/JFace
    Réponses: 2
    Dernier message: 22/06/2004, 21h40
  5. [debug] fuites mémoires
    Par tmonjalo dans le forum C
    Réponses: 3
    Dernier message: 28/07/2003, 17h20

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