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 :

garbage collector, compteur de reference


Sujet :

C++

  1. #21
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    moi je n'ai toujours pas compris si il fallait gerer les references dans 1. un seul objet graph (compliqué ou non) ou dans 2. tout le programme.

    si c'est 2. alors la solution de medinoc est bonne.

  2. #22
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    Screetch, je ne pense pas t'avoir demander de me générer le vcproj
    J'ai simplement demander a tout les lecteurs si quelqu'un l'avait déja utilisé avec visual, et dans ce cas savoir si je peux downloader le .sln quelque part, ou qu'on puisse me le fournir moyennant de ma part un grand merci, un merci d'un développeur de la communauté qui galere malheuresement comme beaucoup...
    Merci du tuyau, je vais générer le projet avec NMAKE et voir ce que ca donne, super

  3. #23
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    un GC me parait overkill pour ce probleme, mais bon ...
    en plus avec des problemes de portabilité à prévoir

  4. #24
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    Oui mais je pense que je n'ai pas trop le choix, j'ai des centaines de references croisées et auto-references, ca génere des memory leaks.
    D'ailleurs y a 2 projets opensource qui font la meme chose que ma javascript virtual machine , Spidermonkey et Rhino, les 2 utilisent un GC certainement pour les meme raisons que moi.
    SpiderMonkey est lent a cause du GC apparemenent, et Rhino a des fuites memoires...
    Si tu a une autre idée que ce GC je suis prenant.
    Merci

  5. #25
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    tu parles de graph ou de programme?

    1. un objet graphe avec des noeuds?
    2. un programme avec plein d'objet se référençant?

    le premier est "facile", le deuxième l'est nettement moins et ressemblerait a un programme java.

    pour le deuxième, c'est pas facile... il faut passer par encapsuler tes pointeurs dans des objets qui gardent les références... mais c'est dur à dire sans même voir un bout de code :-/

  6. #26
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    J'ai pas tout compris alors je me contente d'un "+1" évocateur

    Tu ne peux pas utiliser de librairie, mais tu peux écrire du code quitte à faire du copier/coller/adapter des sources d'une librairie connue ou d'ailleurs.

    Voici un petit bout de code qui rejoint la proposition de Médinoc:
    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
    template<class T>
    class c2smart_ptr
    {
    	T *f_ptr;
    	c2smart_ptr<T> *f_ap,*f_apr;
    	void Attach(const c2smart_ptr<T> *p)
    	{
    		f_apr=(f_ap=p->f_ap)->f_apr;
    		f_ap->f_apr=f_apr->f_ap=this;
    	}
    	void Detach()
    	{
    		f_ap->f_apr=f_apr;
    		f_apr->f_ap=f_ap;
    	}
    public:
    	c2smart_ptr()
    		:f_ptr(0) {f_ap=f_apr=this;}
    	explicit c2smart_ptr(T *ptr)
    		:f_ptr(ptr) {f_ap=f_apr=this;}
    	template<class Y>
    	c2smart_ptr(const c2smart_ptr<Y> & r)
    		:f_ptr(r.get()) { Attach(reinterpret_cast<const c2smart_ptr<T> *>(&r)); }
    	c2smart_ptr(const c2smart_ptr<T> & r)
    		:f_ptr(r.f_ptr) { Attach(&r); }
    	c2smart_ptr<T> & operator=(const c2smart_ptr<T> & r)
    	{
    		if (&r!=this)
    		{
    			c2smart_ptr<T> t(*this); //keep this line !
    			Detach();
    			f_ptr=r.f_ptr;
    			Attach(&r);
    		}
    		return *this;
    	}
    	~c2smart_ptr()
    	{
    		if (f_ap==this)
    			delete f_ptr;
    		else
    			Detach();
    	}
    	T & operator*() const
    		{ return *f_ptr; }
    	T *operator->() const
    		{ return f_ptr; }
    	T *get() const
    		{ return f_ptr; }
    };
    C'est un smart pointer qui maintient ses références dans une liste doublement chainée.
    Simple, concis et vérifié (par moi , et bientôt par toute la communauté C++ de developpez.net )

  7. #27
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    merci a tous, copier du code serait inutile dans ce cas.
    Pour expliquer ce que j'entend pas object graph est-il possible ici de poster un lien vers une page web? ou cela est interdit?

  8. #28
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut


    voila ce que j entend par object graph, ce sont des objets contenant des references sur d autres objets, sur eux memes, etc...
    Le probleme est qu avec des refcount, il n est pas possible de gerer les references cycliques ou autoreferences.
    Tout la est mon probleme, les objet 3, 5 et 6 ne sont pas deletable, il faut manuellement casser les references croisees et auto pour eviter les memory leaks. Ou bien utiliser des weaks pointers, mais c est pas evident vu la complexite avancee de mon object graph, celui ci est juste un exemple tres facile a gerer.
    Voila en esperant un peu d aide
    Merci

  9. #29
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Ce serait intéressant de voir un bout de code qui représente ce shéma, et montrer que des smart pointer ne suffiraient pas.
    Comme ça, à froid:
    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
    struct Object {
    std::list< shared_ptr<Object> > f_obj_list;
    };
     
    shared_ptr<Object> o1,o2,o3,o4,o5,o6;
    o1=make<Object>();
    o2=make<Object>();
    o3=make<Object>();
    o4=make<Object>();
    o5=make<Object>();
    o6=make<Object>();
    o1.f_obj_list.insert(o3);
    o1.f_obj_list.insert(o4);
    o2.f_obj_list.insert(o4);
    o3.f_obj_list.insert(o5);
    o5.f_obj_list.insert(o3);
    o6.f_obj_list.insert(o5);
    o6.f_obj_list.insert(o6);

  10. #30
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    j ai jamais travailler avec la SL sharedpointer, en fait je dirais plutot :
    Dans le diagramme chaque case est l instance elle meme(a), pas la reference(b).
    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
     
    class MyClass
    {
    shared_ptr<MyClass> m_ref1;
    shared_ptr<MyClass> m_ref2;
    };
     
    //main, la on cree toutes les objets(cases dans le schema)
    shared_ptr<MyClass> o1 = new MyClass(); // la syntaxe est surement fausse, c est juste pour montrer le principe
    shared_ptr<MyClass> o2 = new MyClass();
    shared_ptr<MyClass> o3 = new MyClass();
    shared_ptr<MyClass> o4 = new MyClass();
    shared_ptr<MyClass> o5 = new MyClass();
    shared_ptr<MyClass> o6 = new MyClass();
     
    //la on "cree" les fleches dans le schema(references)
     o1.m_ref1 = o3; //fleche o1->o3 
     o1.m_ref2 = o4; //fleche o1->o4 
     
    o2.m_ref1 = o4;
     
    // ref croisee
    o3.m_ref1 = o5;
    o5.m_ref1 = o3;
     
    o6.m_ref1 = o5;
    o6.m_ref2 = o6;
    Donc quand tu quitte ton main admettons que o1 soit deleter le premier, o4 reste en vie car retenu par o2, puis si tu delete o2, o4 est delete aussi.
    Par contre tout le reste n est jamais deleter car o3 et o5 sont retenus mutuellement, leur refcount est pour o3=1(retenu par o5), o3=2(retenu par o3 et o6) et o6=1(retenu par lui meme).
    Il est possible de manuellement casser la reference croisee o3-o5 et l autoreference o6-o6, avant de quitter le main. Dans ce cas chaque destruction entraine une autre, tout est deleter.
    Mon souci majeur est que ce schema est ridiculement simple, ce que j ai en realite est 50 fois plus complique, et quand je dis 50 fois c est vraiment pas une blague.
    Sans compter que ce schema dans mon cas reel est dynamique, selon le contexte, j ai un schema different.
    La question initiale de ce post, est de savoir comment regler ce probleme sans garbage collector...
    Merci

  11. #31
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    En effet, ce petit bout de code prouve le memory leak:
    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
    #include "boost/make_shared.hpp"
    #include <list>
     
    struct Object
    {
    	std::list< boost::shared_ptr<Object> > f_obj_list;
    	int f_n;
    	Object(int n):f_n(n) {std::wcout << "Object " << f_n << std::endl;}
    	~Object() {std::wcout << "~Object " << f_n << std::endl;}
    };
     
    int main()
    {
    	boost::shared_ptr<Object> o1,o2,o3,o4,o5,o6;
    	o1=boost::make_shared<Object>(1);
    	o2=boost::make_shared<Object>(2);
    	o3=boost::make_shared<Object>(3);
    	o4=boost::make_shared<Object>(4);
    	o5=boost::make_shared<Object>(5);
    	o6=boost::make_shared<Object>(6);
    	o1->f_obj_list.push_back(o3);
    	o1->f_obj_list.push_back(o4);
    	o2->f_obj_list.push_back(o4);
    	o3->f_obj_list.push_back(o5);
    	o5->f_obj_list.push_back(o3);
    	o6->f_obj_list.push_back(o5);
    	o6->f_obj_list.push_back(o6);
    }
    Moi qui croyait que les smart pointer était la solution à tous les maux provoqués par les pointeurs (j'ai jamais eu non plus à gérer des références cycliques)

    Ben à mon avis, les réponses à ta question intiale sont:
    1) tolérer les memory leak
    2) revoir le concept de l'application
    3) retenir toutes les instances lors de leur création et vérifier périodiquement, une par une, si elles sont toujours viables (suivant quelle critère ?)

    Quoiqu'il en soit, je serais curieux de savoir comment tu auras résolu ton problème.

  12. #32
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    tu as lu mon post ?
    http://www.developpez.net/forums/d82...e/#post4769669

    du moment que tu as un graph que tu peux parcourir alors c'est possible.

    la je pense qu'il faudra stoker tous les pointeurs de tes objets puis parcourir ton graph pour identifier les manquant, ceux que tu devras effacer avec delete.

    <EDIT>il y a moyen de mieux faire avec de l'incremental donc d'eviter de stoker en double toutes les references</EDIT>

    je ne sais pas comment est fait ton graph, tu diras peut-etre voire surement que c'est trop dur, alors montre nous un bout de code pour expliquer comment est concrètement fait ton graph

  13. #33
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    oui j'ai lu ton post, grosso modo le principe est de garder une trace des references, mais a quel moment dois-je enclencher la deletion des objets restants??
    Mon application crée en permanence des references cycliques et en perd la trace. A quel moment donc les deleter?
    Cela revient finalement a un garbage collector...

  14. #34
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    option 1: tu pourrais surcharger l'operateur "new" pour garder la trace de tous les objets, ainsi quand tu veux, tu peux parcourir ton graph et identifier les manquants

    option 2: tu surcharges l'operateur "delete" (attention: ne pas deleter ses noeuds pour ne pas faire de recursion) pour garder les références peut-etre effacées, ensuite quand tu parcours ton graph, tu enleves de la liste ceux qui sont encore presents dans le graph, et tu inspectes les noeuds descendant de ceux que tu veux effacer... il est donc incremental puisqu'il faudra attendre le parcours suivant pour les effacer (ou pas)

    Quand declencher ce parcours du graph et lu suppression effective avec "delete"?

    A. soit un thread a part qui declenche l'operation tous les x millisecond
    B. tu testes a un endroit de ton code si la liste fait plus que n elements, tu declencles l'operation

    l'option A est plus delicate car il faudra protéger ton graph (les "ajouts" de noeuds + surement autre chose que j'oublie)

    oui c'est une sorte de GC, mais spécialisé pour ton cas et surement plus multi-plateform qu'un vrai GC type Boehm.
    J'ai cru comprendre que l'option multi plateform était ton intérêt premier non?
    d'autre part, par exemple, le GC de objective C sur i-phone n'est pas disponible sur i-phone... donc je dirais que les GC généraux sont peut-etre un problème avec des ressources limitées.

    <EDIT> les GC sont vraiment un domaine a part entière, j'ai cru comprendre que javascript core (webkit) le faisait par analyse de l'AST.
    http://trac.webkit.org/wiki/JS%20Cor...ge%20Collector

    question: Pourquoi avez-vous développé votre propre javascript compilateur?
    javascript core de webkit ne répondait pas du tout au besoin?

    </EDIT>

  15. #35
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    en fait il s'agit un javascript compilé, un .js compilé en .cjs. Car pour un telephone mobile, un interpreteur est trop lent. Ma JSVM execute le bytecode du cjs.
    Pour cela l'application est designée avec des references cycliques.
    C'est similaire a SpiderMonkey ou Rhino.
    Bon on a une version Java de cet JSVM, je l'ai porté en natif.

  16. #36
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    penses-tu que faire ce que je propose est possible ou non?

  17. #37
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 91
    Par défaut
    B: tu testes a un endroit de ton code si la liste fait plus que n elements, tu declencles l'operation
    ton option B, disons, a quel endroit dois-je enclencher l'opération??Quand ma memoire physique disponible atteint un seuil?
    Tu pourrais détailler stp, et pour repondre a ta question precedente, oui le multi-platforme est mon probleme principal.
    J'avais pensé a la base a memoriser les references cycliques quelque part, et les deleter a un certain moment avec un thread.
    Cependant, le design de notre application a changé entre temps et on a un object graph d'une complexité bien plus avancée.

  18. #38
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    j'aurais par exemple fait un thread qui envoie un message tous les x (milli)secondes donc comme ca tu n'aurais pas eu besoin de proteger ton code contre les acces concurrentiels...

    ... remarque, un timer marche aussi comme cela.

    si tu ne peux faire ni l'un ni l'autre,
    alors je l'aurais placé dans la boucle a message...

    si tu n'en as pas, tu peux toujours le mettre dans l'operateur delete.
    ... et finalement tout compte fait, dans le "delete", ne serait-ce pas la meilleure solution?

    <EDIT> avec une durée minimal entre 2 lancements, et/ou un nombre minimal d'objets à tester </EDIT>

  19. #39
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Plus de memory leak avec 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #include "boost/make_shared.hpp"
    #include "boost/smart_ptr/weak_ptr.hpp"
    #include <list>
     
    struct Object
    {
    	std::list< boost::weak_ptr<Object> > f_obj_list;
    	int f_n;
    	Object(int n):f_n(n) {std::wcout << "Object " << f_n << std::endl;}
    	~Object() {std::wcout << "~Object " << f_n << std::endl;}
    };
     
    int main()
    {
    	boost::shared_ptr<Object> o1,o2,o3,o4,o5,o6;
    	o1=boost::make_shared<Object>(1);
    	o2=boost::make_shared<Object>(2);
    	o3=boost::make_shared<Object>(3);
    	o4=boost::make_shared<Object>(4);
    	o5=boost::make_shared<Object>(5);
    	o6=boost::make_shared<Object>(6);
    	o1->f_obj_list.push_back(o3);
    	o1->f_obj_list.push_back(o4);
    	o2->f_obj_list.push_back(o4);
    	o3->f_obj_list.push_back(o5);
    	o5->f_obj_list.push_back(o3);
    	o6->f_obj_list.push_back(o5);
    	o6->f_obj_list.push_back(o6);
    }
    Dites les pros du smart pointer, vous auriez pu dire qu'il suffisait d'utiliser weak_ptr

  20. #40
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    non un weak_ptr ne locke pas contre la destruction...
    un weak_ptr est un pointeur amélioré dans le sens ou tu peux savoir qu'un objet est deleté. C'est aussi pour ca qu'il se construit a partir d'un shared_ptr

    <EDIT> ton exemple ne marche que parce que tu as fait des smart_ptr pour tous les objets au début. ce n'est donc pas un graph ...
    </EDIT>

    un extrait tiré de la doc de boost:

    Q. Can an object create a weak_ptr to itself in its constructor?

    A. No. A weak_ptr can only be created from a shared_ptr, and at object construction time no shared_ptr to the object exists yet. Even if you could create a temporary shared_ptr to this, it would go out of scope at the end of the constructor, and all weak_ptr instances would instantly expire.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. [JVM] Java 5 et Garbage Collector(Parralèle)
    Par ssaunois dans le forum Général Java
    Réponses: 6
    Dernier message: 29/11/2005, 00h42
  2. [JVM]Garbage collector
    Par godik dans le forum Général Java
    Réponses: 5
    Dernier message: 07/10/2005, 10h12
  3. JPanel et Garbage Collector
    Par tck-lt dans le forum Agents de placement/Fenêtres
    Réponses: 9
    Dernier message: 25/07/2005, 19h03
  4. [JVM] les objets et le Garbage collector
    Par Kurdran dans le forum Général Java
    Réponses: 7
    Dernier message: 02/06/2005, 17h57
  5. [Language]Garbage collector
    Par GETah dans le forum Langage
    Réponses: 2
    Dernier message: 23/03/2005, 16h18

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