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

Langage C++ Discussion :

faire une macro new


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 25
    Points : 15
    Points
    15
    Par défaut faire une macro new
    bonjour,

    Dans le cadre de la réalisation d'un gestionnaire de mémoire, j'ai besoin de créer une macro qui se comporte de la même manière qu'un new, mais sans l'utiliser.
    Je n'ai pas le droit d'utiliser le new, car faisant du middleware, il faut laisser au cilient la possibilité de faire sa propre surcharge de new qui potentiellement pourrait utiliser un autre allocateur que celui que j'utilise en interne.

    Donc je voudrais un truc du genre
    MyClass* ptr = MY_NEW MyClass(param1, param2);
    dans l'idéal
    ou peut être de manière plus réaliste
    MyClass* ptr = MY_NEW(MyClass, param1, param2);


    Est-ce possible?

    Est-ce que:
    MyClass* ptr = (MyClass*)malloc(sizeof(MyClass));
    ptr->MyClass(param1, param2);
    et
    MyClass* ptr = new MyClass(param1, param2);
    sont équivalents?


    Merci d'avance pour vos réponses

  2. #2
    Membre averti Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Points : 323
    Points
    323
    Par défaut
    Bonsoir,

    Est-ce que:
    MyClass* ptr = (MyClass*)malloc(sizeof(MyClass));
    ptr->MyClass(param1, param2);
    et
    MyClass* ptr = new MyClass(param1, param2);
    sont équivalents?
    Oui sauf que on ne doit pas faire un delete sur une mémoire allouée par malloc, et inversement, il ne faut donc pas confondre malloc et new.

    Pour faire ce que tu veut, on utilise habituellement le placement new:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyClass* ptr = new(MonAllocateur(sizeof(MyClass))) MyClass(param1, param2);

    Donc je voudrais un truc du genre
    MyClass* ptr = MY_NEW MyClass(param1, param2);
    dans l'idéal
    ou peut être de manière plus réaliste
    MyClass* ptr = MY_NEW(MyClass, param1, param2);
    On peut faire quelque chose comme ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define MY_NEW(T) new(MonAllocateur(sizeof(T))) T
     
    MyClass* ptr = MY_NEW(MyClass)(param1, param2);
    Cela dit cette méthode n'est pas recommandée, d'une part car elle utilise des macro, mais aussi parque tu risque de faire un delete normal sur un objet alloué avec autre chose qu'un new.

    La meilleur solution a mon avis, est de surcharger les new et delete spécifique de tes classe concernée.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 25
    Points : 15
    Points
    15
    Par défaut
    Citation Envoyé par Nogane Voir le message
    On peut faire quelque chose comme ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define MY_NEW(T) new(MonAllocateur(sizeof(T))) T
     
    MyClass* ptr = MY_NEW(MyClass)(param1, param2);
    Cela dit cette méthode n'est pas recommandée, d'une part car elle utilise des macro, mais aussi parque tu risque de faire un delete normal sur un objet alloué avec autre chose qu'un new.
    Merci pour cette solution je n'y avais pas pensé
    Je pense utiliser quelque chose comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #define MY_NEW(T) new(MyAlloc(sizeof(T), __FILE__, __LINE__)) T
     
    template<class T> void MY_DELETE(T* p)
    {
    	p->~T();
    	MyFree(p);
    }
    Qu'est ce que cela implique exactement d'utiliser ce code en termes de
    -performances
    -sécurité
    -temps de compilation
    -taille du programme
    ?


    Citation Envoyé par Nogane Voir le message
    La meilleur solution a mon avis, est de surcharger les new et delete spécifique de tes classe concernée.
    J'avais pensé utiliser cette solution en créant une classe MyObject dont dériverait chacune de mes autres classe, et qui surchargerait l'opérateur new et delete pour passer par mon manager, mais c'est un peu lourd comme solution. Cela impliquerait beaucoup trop de changements.

    En tout cas merci pour ta réponse

  4. #4
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    As tu pensé à une surcharge globale de new/new[] et delete/delete[] ?

    Ca évite de bidouillage/hack sur new avec des macro qui est un code smell et surtout une très grosse source de bugs.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  5. #5
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    As tu pensé à une surcharge globale de new/new[] et delete/delete[] ?

    Ca évite de bidouillage/hack sur new avec des macro qui est un code smell et surtout une très grosse source de bugs.
    Je crois qu'il veut pas le faire car il veut pas "obliger" l'utilisateur final à passer par sa surcharge. Qui a mon avis n'est pas un réel problème, il suffit de mettre la surcharge dans son propre espace de noms.

  6. #6
    Membre averti Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Points : 323
    Points
    323
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define MY_NEW(T) new(MyAlloc(sizeof(T), __FILE__, __LINE__)) T
    template<class T> void MY_DELETE(T* p)
    Qu'est ce que cela implique exactement d'utiliser ce code en termes de:
    -performances
    Pour les performance ca dépend surtout de ton allocateur.

    -sécurité
    C'est le principale problème: Une macro c'est obscure pour le programmeur, et le compilateur n'as aucun moyen de tester ca validité d'un point de vue C++. C'est le préprocesseur qui gère, et il est "bête et méchant". En plus tu risque fort d'avoir des problème si tu alloue avec une méthode et désalloue avec une autre. Et ne dit pas "Il suffit d'y penser", quand on dit ca c'est qu'on est déjà entrain de ce tirer une balle dans le pied.

    -temps de compilation
    Effet probablement dérisoire.

    -taille du programme
    Effet dérisoire aussi.


    Je me demande si tu fait ca juste pour détecter les fuite mémoire, corriger des fuites, ou pour réellement modifier ton allocateur?
    - Dans le première cas, un simple conteur d'instance devrai pourvoir te rassurer, et tu n'aurais même pas a le mètre dans le produit final.
    - Dans le deuxième cas, dit toi qu'il suffit généralement d'appliquer proprement le RAII (par exemple: vector,scoped_ptr,shared_ptr) pour que les fuite mémoires disparaissent d'elle même. Si elles restent après ca, il sera toujours temps d'en reparler.
    - Dans le troisième cas, ce n'est que rarement utile, mais bon, la meilleur solution reste de surcharger tes new/delete. Ca peut ce faire très proprement, en héritant d'une class qui fait tout pour toi. Tu n'as plus qu'a spécifier ton allocateur.
    Je doit avoir ca dans un coin donc n'hésite pas a me demander le code. pareil pour le conteur d'instance.

  7. #7
    screetch
    Invité(e)
    Par défaut
    tu pourrais faire un override global de new/delete et proposer un moyen de changer les allocateurs en demandant un set de fonctions malloc/free

  8. #8
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Es-tu au courant que tu peux définir des versions spécifiques à la classe des opérateurs new et delete?
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 25
    Points : 15
    Points
    15
    Par défaut
    Citation Envoyé par JulienDuSud Voir le message
    Je crois qu'il veut pas le faire car il veut pas "obliger" l'utilisateur final à passer par sa surcharge. Qui a mon avis n'est pas un réel problème, il suffit de mettre la surcharge dans son propre espace de noms.
    C'est exactement cela.
    par contre on ne peut pas faire de surcharge de new/delete dans un espace de noms. Le compilateur me renvoit l'erreur:
    allocation/deallocation functions shall be global scope or class members


    Citation Envoyé par Nogane Voir le message
    En plus tu risque fort d'avoir des problème si tu alloue avec une méthode et désalloue avec une autre. Et ne dit pas "Il suffit d'y penser", quand on dit ca c'est qu'on est déjà entrain de ce tirer une balle dans le pied.
    Je ne pense pas que ce soit un problème, à partir du moment où l'on impose de passer par une macro, après il suffit de faire des recherches sur delete/new et ça se détecte très rapidement. Mais je suis d'accord que s'il y avait une solution transparente ça serait beaucoup mieux.

    Citation Envoyé par Nogane Voir le message
    Je me demande si tu fait ca juste pour détecter les fuite mémoire, corriger des fuites, ou pour réellement modifier ton allocateur?
    En fait le but est
    1) de pouvoir tracer la mémoire (connaitre la mémoire allouée à tout moment, les leaks, affichiers noms de fichiers et numéros de lignes des appels de new/delete, afficher la call-stack...)
    2)avoir un allocateur interne différent de l'allocateur client.

    Citation Envoyé par Nogane Voir le message
    - Dans le deuxième cas, dit toi qu'il suffit généralement d'appliquer proprement le RAII (par exemple: vector,scoped_ptr,shared_ptr) pour que les fuite mémoires disparaissent d'elle même. Si elles restent après ca, il sera toujours temps d'en reparler.
    Certes mais cela ne répond pas vraiment à mes besoins. Mais je suis d'accord que cela permet d'éviter des fuites mémoires.

    Citation Envoyé par Nogane Voir le message
    - Dans le troisième cas, ce n'est que rarement utile, mais bon, la meilleur solution reste de surcharger tes new/delete. Ca peut ce faire très proprement, en héritant d'une class qui fait tout pour toi. Tu n'as plus qu'a spécifier ton allocateur.
    Je doit avoir ca dans un coin donc n'hésite pas a me demander le code. pareil pour le conteur d'instance.
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Es-tu au courant que tu peux définir des versions spécifiques à la classe des opérateurs new et delete?
    oui je suis au courant, mais je n'ai pas envie d'utiliser cette solution qui est trop lourde. Il y aurait beaucoup trop de code à traiter et je crois pas que rajouter de l'héritage partout soit très bon pour les perfs.


    Citation Envoyé par screetch Voir le message
    tu pourrais faire un override global de new/delete et proposer un moyen de changer les allocateurs en demandant un set de fonctions malloc/free
    Je n'ai malheureusement pas le droit de faire un override global de new/delete pour des raisons évoquées plus haut.

Discussions similaires

  1. [Débutant] Faire une macro
    Par Homer091 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 14/05/2008, 14h48
  2. Faire une macro de tri
    Par willyol3 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 23/04/2008, 21h08
  3. Appeler un fichier XL déjà ouvert pour faire une macro
    Par oliver75 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 31/05/2007, 12h33
  4. faire une macro pour un sous formulaire
    Par db48752b dans le forum Access
    Réponses: 2
    Dernier message: 18/09/2006, 23h14

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