Aller au contenu
  • Pas encore inscrit ?

    Pourquoi ne pas vous inscrire ? C'est simple, rapide et gratuit.
    Pour en savoir plus, lisez Les avantages de l'inscription... et la Charte de Zébulon.
    De plus, les messages que vous postez en tant qu'invité restent invisibles tant qu'un modérateur ne les a pas validés. Inscrivez-vous, ce sera un gain de temps pour tout le monde, vous, les helpeurs et les modérateurs ! :wink:

Messages recommandés

Posté(e)

Je ne suis pas certain d'avoir bien suivi toute la technique mais je voulais juste dire un truc : nous ne sommes ni en Java ni en .Net. Il n'y a donc pas de Garbage Collector, donc le simple fait de nullifier des pointeurs ne va pas faire grand chose, il faut penser à libérer soi-même et explicitement la mémoire allouée.

Posté(e)
Je ne suis pas certain d'avoir bien suivi toute la technique mais je voulais juste dire un truc : nous ne sommes ni en Java ni en .Net. Il n'y a donc pas de Garbage Collector, donc le simple fait de nullifier des pointeurs ne va pas faire grand chose, il faut penser à libérer soi-même et explicitement la mémoire allouée.

519121[/snapback]

Alors pour répondre à ta question, en effet c'est du C++ donc pas de ramasse-miettes. Toutefois la classe TImage hérite de TComponent qui a entre autres caractéristiques que les objets en dérivant sont automatiquement effacés à la fin du programme sans que le programmeur utilise delete.

 

TImage contient comme donnée membre Picture qui est un TPicture*. TPicture a notamment en charge de stocker en mémoire l'image à afficher. Si plusieurs TImage doivent afficher la même image, pour économiser de la mémoire, on peut s'arranger pour que les membres Picture de tous les TImages concernés pointent vers le même objet TPicture (par écriture directe de la zone contenant Picture de chaque Timage).

 

Le problème c'est que si on laisse le programme se finir en l'état, lors de la destruction des TImage, l'objet Picture qui est en fait le même pour plusieurs TImage va être effacé plusieurs fois de suite (une fois par TImage). Ce qui conduit inévitablement à une fin de programme pas très glorieuse. La solution de facilité consiste à placer ces pointeurs à NULL de façon à ce que delete soit sans effet (puisque delete NULL ne produit aucune erreur).

 

Là où ce n'est pas très rigoureux, c'est que les objets Picture initiaux des TImage modifiés ne sont pas effacés, eux (leur adresse est perdue avec le code que j'ai donné). En pratique cela n'a aucune importance puisque le programme se fini à ce moment là. La mémoire est donc récupérée de toute façon.

 

Je vais poster une classe qui fait tout cela rationellement en bon C++, et sans perdre les TPicture* substitués.

Posté(e) (modifié)

.h

#include <map>

class PartTImage
{
typedef std::map<TImage*,TPicture*> MTIP;
typedef MTIP::iterator I_MTIP;

    public:
         PartTImage();  // Constructeur par défaut
         PartTImage(TImage*); // Constructeur en spécifiant le TImage source
         ~PartTImage();
         bool __fastcall Partage(TImage* dest); // Partage avec le dernier TImage source
         bool __fastcall Partage(TImage* source, TImage* dest); // Partage en redéfinissant le TImage source
         inline TImage* Source() { return pTISource; }; // Retourne le TImage* source actuel
         bool __fastcall EstPartage(TImage*); // Le TImage fait-il partie des TImage partagés ?
         bool __fastcall Departage(TImage*);  // Enlève le partage sur un TImage

    private:
         inline I_MTIP Trouve(TImage* pti) { return mPart.find(pti); };
         void __fastcall Separe(I_MTIP);
         TImage* pTISource;
         MTIP mPart;
};

.cpp

PartTImage::PartTImage()
{
    pTISource = NULL;
}
PartTImage::PartTImage(TImage* pti)
{
    pTISource = pti;
}
PartTImage::~PartTImage()
{
    for (I_MTIP it = mPart.begin(); it != mPart.end(); it++) Separe(it);
}
bool __fastcall PartTImage::Partage(TImage* pTIS, TImage* pTID)
{
    pTISource = pTIS;
    return Partage(pTID);
}
bool __fastcall PartTImage::Partage(TImage* pTID)
{
    if (!pTISource) return false;
    if (!pTID) return false;

    mPart[pTID] = pTID->Picture;
    TPicture** ppTP = &(pTID->Picture);
    *ppTP = pTISource->Picture;
    return true;
}
bool __fastcall PartTImage::EstPartage(TImage* pti)
{
    I_MTIP it = Trouve(pti);
    return (it != mPart.end());
}
bool __fastcall PartTImage::Departage(TImage* pti)
{
    I_MTIP it = Trouve(pti);
    if (it == mPart.end()) return false;
    Separe(it);
    mPart.erase(it);
    return true;
}
void __fastcall PartTImage::Separe(I_MTIP it)
{
    TPicture** ppTP = &(it->first->Picture);
    *ppTP = it->second;
}

 

Pour l'utiliser il suffit d'instancier un objet PartTImage (avec new), soit en spécifiant le TImage source (qui contient l'image) soit sans le spécifier. Ensuite l'appel aux fonctions Partage() permet de partager l'image : soit en spécifiant le TImage source en premier paramètre et le TImage qui va recevoir l'image en second paramètre ou bien on ne spécifie que le Timage qui doit recevoir l'image. Dans ce cas, le TImage source utilisé sera le dernier spécifié.

 

pPTI = new PartTImage();
pPTI->Partage(Image1, Image2); // Utilise Image1 comme source
pPTI->Partage(Image3); // Utilise Image1 comme source
pPTI->Partage(Image4, Image5); // Utilise Image4 comme source
pPTI->Partage(Image6); // Utilise Image4 comme source

Etant entendu que pPTI est déclaré comme membre la fenêtre (Form1) en tant que PartTImage* et qu'il faut faire "delete pPTI;" à la fin du programme (OnDestroy).

Modifié par _Michel_
Posté(e)

Hello,

 

Bon dejà, desolé de pas avoir répondu plus tôt j'étais occupé sur une autre partie du projet.

 

Donc j'ai essayé ta solution ça marche super! donc merci beaucoup!

 

Et pour info j'ai également essayé avec la méthodes Assign() de Picture et ça marche nikel aussi sauf que il n'y a pas de probleme à la fermeture du programme à cause des pointeurs.

 

 

Et au niveau utilisation de mémoire je n'ai noté aucune différence entre les deux méthodes.

 

Encore merci beaucoup

Posté(e)
Et pour info j'ai également essayé avec la méthodes Assign() de Picture et ça marche nikel aussi sauf que il n'y a pas de probleme à la fermeture du programme à cause des pointeurs.

Et au niveau utilisation de mémoire je n'ai noté aucune différence entre les deux méthodes.

Normalement Assign fait une copie de l'objet donc c'est normal qu'il n'y ait aucun problème d'effacements multiples. Là où je ne comprends pas, c'est que ça devrait consommer de la mémoire. Je ferais l'essai quand je reviendrais sous windows.

Posté(e)

Résultat des tests :

 

Il s'agit d'un programme avec 3 TImage, lancé sous C++ Builder. Une seule image est utilisée, il s'agit d'un JPEG de 701 Ko (1632x1232).

 

Image chargée manuellement dans les 3 Timage : 28 184 Ko utilisé

Une seule image chargée, les autres vides : 13 548 Ko utilisé.

Une image chargée, Assign() pour les deux autres : 25 396 Ko utilisé

Une image chargée, PartTImage pour les deux autres : 13 564 Ko utilisé

 

Globalement les choses se passent bien comme je l'imaginais. Assign() fait bien une copie avec amputation de la mémoire. Il semble que ce soit toutefois un peu plus avantageux que le chargement séparé des trois images (pour des raisons que j'ignore).

PartTImage ne consomme pratiquement rien de plus que la seule image chargée.

Rejoindre la conversation

Vous pouvez publier maintenant et vous inscrire plus tard. Si vous avez un compte, connectez-vous maintenant pour publier avec votre compte.
Remarque : votre message nécessitera l’approbation d’un modérateur avant de pouvoir être visible.

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

  • En ligne récemment   0 membre est en ligne

    • Aucun utilisateur enregistré regarde cette page.
×
×
  • Créer...