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 :

un peu de voltige avec new


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    screetch
    Invité(e)
    Par défaut un peu de voltige avec new
    je cherche a inserer quelques infos lors de l'appel a l'operateur new en le mettant dans une macro. alors inserer le nom du fichier, ca je sais faire. je voudrais maintenant avoir un peu plus d'info (non, pas la ligne, ca aussi je sais faire!)

    mon but serait de creer a la volée une instance statique de LocationInfo, qui contiendra le nom du fichier et la ligne, un pointeur sur un autre LocationInfo pour les mettre dans une liste chainée, et quelques valeurs de base (genre combien d'allocs ont ete realisées, etc). ainsi j'obtiens une liste chainée de tous les appels a new, avec le nombre d'appels, je peux verifier quel endroit alloue le plus, etc.

    j'ai tout ce qu'il faut pour le faire sauf l'instance de LocationInfo que je n'arrive pas a créer a la volée.

    par exemple j'aimerai que le code

    s'étende en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int* a = (static LocationInfo info(__FILE__, __LINE__, __FUNCTION__)), new(&info) int;
    evidemment cela ne compile pas du tout, je cherche a le faire rentrer de force dans le compilateur!! (oui c'est pas malin :p)
    je pense qu'il y a un moyen de conserver la syntaxe _new type; sinon l'autre possibilité est de faire
    int* a;
    _new(a, int);
    mais ca ne me plait pas, je prefererais garder la "r-value" intacte.

    j'ai pensé a :
    - utiliser l'operateur ,
    - mettre une boucle ou un truc du meme style;
    - declarer une classe a cet endroit avec un champ statique
    mais aucune de ces methodes n'autorise la declaration d'une variable a cet endroit

    d'autres pistes ?

  2. #2
    Membre expérimenté Avatar de Kujara
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 262
    Par défaut
    Operateur << sur une classe, c'est beau :

    #define new MemoryManager::GetSingleton() << MemoryBlock( __FILE__, __FUNCTION__, __LINE__) << new
    Et ça marche.

  3. #3
    screetch
    Invité(e)
    Par défaut
    mais tu saurais rendre le memory block static ?

    je voudrais creer un memory block par endroit ou on appelle new, pas par appel de new.

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Je vois bien un truc de ce genre:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* Doit être static, pour que chaque variable static n'appartienne qu') un seul source. */
    template< int L >
    static inline LocationInfo* MakeLocationInfo( std::string const &file, std::string const &function)
    {
    	static LocationInfo info(file, L, function);
    	return &info;
    }
     
    #define _new new(MakeLocationInfo< __LINE__ >(__FILE__, __FUNCTION__))
    Mais je n'ai pas testé, je ne sais même pas si ça compile.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    screetch
    Invité(e)
    Par défaut
    et bien, ca alloue aussi
    j'essaye quelques bidouilles avec vos propositions et je reviens

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par screetch Voir le message
    mais tu saurais rendre le memory block static ?

    je voudrais creer un memory block par endroit ou on appelle new, pas par appel de new.
    Si tu stockes ensuite les blocks dans un std::set<LocationInfos, ptr>, tu peux t'assurer de leur unicité (ne pas oublier de définir les opérateurs nécessaires sur LocationInfos).

    Sinon, c'est quoi l'intérêt d'avoir les LocationInfos statiques ?
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par screetch Voir le message
    je cherche a inserer quelques infos lors de l'appel a l'operateur new en le mettant dans une macro. alors inserer le nom du fichier, ca je sais faire. je voudrais maintenant avoir un peu plus d'info (non, pas la ligne, ca aussi je sais faire!)

    mon but serait de creer a la volée une instance statique de LocationInfo, qui contiendra le nom du fichier et la ligne, un pointeur sur un autre LocationInfo pour les mettre dans une liste chainée, et quelques valeurs de base (genre combien d'allocs ont ete realisées, etc). ainsi j'obtiens une liste chainée de tous les appels a new, avec le nombre d'appels, je peux verifier quel endroit alloue le plus, etc.

    j'ai tout ce qu'il faut pour le faire sauf l'instance de LocationInfo que je n'arrive pas a créer a la volée.

    par exemple j'aimerai que le code

    s'étende en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int* a = (static LocationInfo info(__FILE__, __LINE__, __FUNCTION__)), new(&info) int;
    Evidemment cela ne compile pas du tout, je cherche a le faire rentrer de force dans le compilateur!! (oui c'est pas malin :p)
    je pense qu'il y a un moyen de conserver la syntaxe _new type; sinon l'autre possibilité est de faire
    int* a;
    _new(a, int);
    mais ca ne me plait pas, je prefererais garder la "r-value" intacte.

    j'ai pensé a :
    - utiliser l'operateur ,
    - mettre une boucle ou un truc du meme style;
    - declarer une classe a cet endroit avec un champ statique
    mais aucune de ces methodes n'autorise la declaration d'une variable a cet endroit

    d'autres pistes ?
    Il faut généralement définir un opérateur new global particulier. Il est déconseillé d'utiliser l'un des prototype suivant (mais pas interdit - c'est même spécifiquement autorisé, cf le standard §18.4.1) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void* operator new(std::size_t size) throw(std::bad_alloc);
    void* operator new(std::size_t size, std::nothrow_t&) throw();
    void* operator new[](std::size_t size) throw(std::bad_alloc);
    void* operator new[](std::size_t size, std::nothrow_t&) throw();
    void* operator new(std::size_t size, void* ptr) throw();
    void* operator new[](std::size_t size, void* ptr) throw();
    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void operator new(std::size_t size, const LocationInfo& infos)
      throw(std::bad_alloc)
    {
      void *pointer = ::operator new(size);
      // ...
      return pointer;
    }
    Tu peux ensuite utiliser le précompilateur pour cacher toute la magie de tes modifications :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define MyNew  new(LocationInfo(__FILE__, __LINE__, __FUNCTION__))
    #define new MyNew
    Cette dernière ligne prend avantage d'une particularité du précompilateur : l'expension de new en MyNew puis en new() casse le cycle d'expension des macros (donc new() n'est pas transformé en MyNew(), etc). La même technique est employée dans le MFC (cf. les fichiers C++ qui contiennent la définition #define new DebugNew). Cela te permet d'avoir le même code, que ton opérateur soit utilisé ou non.

    Le code suivant devrait alors fonctionner comme tu le souhaites:
    Le fait de passer LocationInfo par un pointeur n'est pas nécessairement une bonne idée (puisque cela oblige la variable à être statique; hors, tu n'as pas de contrôle véritable sur l'ordre de destruction des variables statiques, donc tu ne peux pas t'assurer que celles-ci existeront toujours une fois sorti de la fonction main() - là ou normalement, tu devrais vérifier si tu as des memory leaks). Il est préférable de copier les informations dans un objet dont tu maitrise la durée de vie.

    Attention aussi à ne pas faire d'allocations dans LocationInfos (pour des raisons évidente de récursivité).

    Pour plus d'information: cf le standard §18.4.1, §3.7.3.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    screetch
    Invité(e)
    Par défaut
    wi alors voila, c'est presque ca (ca ressemble enormement au code que j'ai)

    a noter que definir new ce n'est pas forcément une bonne idée car alors quand on redefinit new dans une classe le compilateur se plaint. ce n'est pas un probleme pour moi, nous utilisons deja une macro _new qui remappe a l'heure actuelle sur new sans rien changer.

    mais maintenant j'aimerai que la LocationInfo soit statique, c'est a dire partagée par tous les "new" qui seront appelé de la.

    exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void test()
    {
      int* a = _new int;
    }
    int main()
    {
      test();
      test();
      LocationInfo::printStats();
    }
    je voudrais que printStats, sans faire aucun calcul (de preference), me reponde :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    main.cpp:3 : 2 calls to new
    vos propositions montreraient quelque chose du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    main.cpp:3 : 1 call to new
    main.cpp:3 : 1 call to new
    voyez vous mon probleme ?

  9. #9
    screetch
    Invité(e)
    Par défaut
    autre avantage d'avoir les LocationInfo statiques : ils existent apres l'appel a la fonction. important pour des stats d'appels de new : par exemple, par frame on a appelé 1800 fois "new" depuis cette ligne dans le fichier : houlala!

    de plus on peut detecter les leaks a l'execution : ce LocationInfo voit son compteur augmenter chaque frame : hop on a le fichier et la ligne du new.

  10. #10
    screetch
    Invité(e)
    Par défaut
    la version de medinoc marche presque

    on a juste un dernier probleme : on utilise des fichiers "master" pour accelerer la compilation, et du coup la fonction est commune a une 20aine de fichier. j'ai la parade, je poste la version complete cet aprem =)

    merci pour l'aide

  11. #11
    screetch
    Invité(e)
    Par défaut
    non en fait je me suis trompé, je pensais avoir resolu mon probleme de master mais en fait non

    en gros je pensais donner un deuxieme argument de template; chaque fois que le fichier .h est inclus, un compteur est incrementé et ce compteur est donné en second argument de template. donc on genere une nouvelle fonction non pas par fichier mais par inclusion du fichier en-tete.

    en gros :

    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
     
    #ifndef COUNTER
    # define COUNTER 0
    #else
    # inc(COUNTER)
    #endif
     
    #ifndef INCLUDED_FILE_H_
    # define INCLUDED_FILE_H_
    /* Doit être static, pour que chaque variable static n'appartienne qu') un seul source. */
    template< int L, int F >
    static inline LocationInfo* MakeLocationInfo( std::string const &file, std::string const &function)
    {
    	static LocationInfo info(file, L, function);
    	return &info;
    }
     #define _new new(MakeLocationInfo<__LINE__,COUNTER>(__FILE__,__LINE__,__FUNCTION__))
    #endif
    le probleme c'est incrementer le compteur

  12. #12
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par screetch Voir le message
    autre avantage d'avoir les LocationInfo statiques : ils existent apres l'appel a la fonction. important pour des stats d'appels de new : par exemple, par frame on a appelé 1800 fois "new" depuis cette ligne dans le fichier : houlala!

    de plus on peut detecter les leaks a l'execution : ce LocationInfo voit son compteur augmenter chaque frame : hop on a le fichier et la ligne du new.
    Oui, mais vu qu'ils sont détruits dans l'ordre inverse de la complétion de leur constructeurs, tu ne peux pas être sûr de leur existence dès lors que tu quittes la fonction main(). Mais c'est bien souvent en dehors de main() qu'on souhaite voir si il existe encore des leaks. Ceci dit, pour faire de l'analyse frame à frame, ça ne pose pas de problèmes.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  13. #13
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Oui, mais vu qu'ils sont détruits dans l'ordre inverse de la complétion de leur constructeurs, tu ne peux pas être sûr de leur existence dès lors que tu quittes la fonction main(). Mais c'est bien souvent en dehors de main() qu'on souhaite voir si il existe encore des leaks. Ceci dit, pour faire de l'analyse frame à frame, ça ne pose pas de problèmes.
    je suis d'accord que c'est souvent apres main que l'on a besoin des leaks mais j'ai aussi besoin de statistiques tres poussées sur les new :
    - qui alloue (quel fichier/ligne)
    - combien de fois par frame
    - quelle quantité (taille, pas nombre d'appels)
    - conbien d'allocs encore en vie

    ces stats seraient ensuite affichées a l'ecran. On pourrait les trier par fichier pour voir toute les allocs dans ce fichier (ou repertoire), on peut aussi les trier åar nombre d'allocs, on peut enfin mettre un "watch" sur des allocs qui grossissent sans jamais maigrir. Tout cela, au runtime et non pas a la fin de l'execution

    nous avons deja beaucoup de statistiques sur la memoire mais on peut en savoir beaucoup plus =)

Discussions similaires

  1. probleme avec new listbox
    Par bubu92 dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 08/11/2006, 17h33
  2. [debutant]Portée d'un objet et creation avec new
    Par harsh dans le forum Débuter
    Réponses: 7
    Dernier message: 17/05/2006, 17h21
  3. [POO] Un peu de mal avec les membres de ma classe
    Par Spack dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 04/11/2005, 03h41
  4. Problème avec new
    Par Azharis dans le forum C++
    Réponses: 18
    Dernier message: 27/04/2005, 17h45
  5. Réponses: 5
    Dernier message: 22/04/2005, 11h38

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