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 :

Namespace et surcharge operator new/delete


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2005
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Namespace et surcharge operator new/delete
    Bonjour,

    Je cherche a surcharger les operateurs new et delete globaux, mais je veux que cette surcharge ne s'applique que dans un namespace en particulier.

    Voici une exemple pour illustrer mes propos

    NameSpace.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #ifndef __MYNAMESPACE_H__
    #define __MYNAMESPACE_H__
     
    namespace MyNameSpace
    {
     void *operator new ( size_t ); 
     void operator delete ( void * );
     
     void Test();
    }
     
    #endif
    NameSpace.cpp
    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
     
    #include <stdafx.h>
     
    #include <stdlib.h>
    #include <stdio.h>
    #include <malloc.h>
     
    #include "NameSpace.h"
     
     void *MyNameSpace::operator new(size_t size)
      {
       return malloc(size);
      }
     
      void MyNameSpace::operator delete (void *Ppt_pt)
      {
       free(Ppt_pt);
      }
     
      void MyNameSpace::Test()
      {
       char *Lsz_val = new char[255];
       delete [] Lsz_val;
      }
    TestNameSpace.pp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include "stdafx.h"
    #include "NameSpace.h" 
     
    using namespace MyNameSpace;
     
    void main(int argc, char* argv[])
    {
     char *Lsz_val = new char[255];
     delete Lsz_val;
     
     Test();
    }
    Le projet compile sans pb avec VC++ 2003 par contre je ne rentre jamais dans mes operateurs new et delete que ca soit dans main ou dans Test !

    Des suggestions ????

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Suggestions :

    1- Surcharger new[] puisque c'est lui que tu utilises
    2- Utiliser delete[], puisque tu alloues avec new[]
    3- Surcharger delete[]
    4- Si le compilo n'utilise pas la bonne version (a priori il le fera dans Test(), mais pas dans main()), indique lui explicitement MyNameSpace::new et MyNameSpace::delete.

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2005
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Bonnes suggestions

    Test : operateurs avec []
    Resultat : aucun changement

    Test : MyNameSpace::new et MyNameSpace::delete
    Resultat : Erreurs a la compilation

    error C2834: 'operator new' must be globally qualified
    error C2834: 'operator delete' must be globally qualified

    Question :
    Est ce que j'essaye de faire est authorise en C++ (je commence a me poser des questions) ou est ce une limitation du VC++ ?

    J'ai beau fouiller dans mes livres sur le C++ ou sur le net j'arrive pas a trouver une confirmation dans un sens ou dans l'autre.


  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    error C2834: 'operator new' must be globally qualified
    error C2834: 'operator delete' must be globally qualified
    Ah oui, maintenant que le compilo en parle ça me rappelle quelque chose. A confirmer, mais je crois effectivement que tu ne peux pas surcharger new et delete dans un espace nommé. Ca ne t'aidera sûrement pas, mais tu peux tout à fait le faire pour une classe particulière par contre.

    Quel est le but exactement ?

  5. #5
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    namespace MyNameSpace
    {
     void *operator new ( size_t );
     void operator delete ( void * );
     void Test();
    }
     void *MyNameSpace::operator new(size_t size)
      {
       return malloc(size);
      }
      void MyNameSpace::operator delete (void *Ppt_pt)
      {
       free(Ppt_pt);
      }
    Ensuite, il faut qualifier les opérateurs new et delete, sinon ce sont les opérateurs par défaut qui sont appelés
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      void MyNameSpace::Test()
      {
       char *Lsz_val = MyNameSpace::new char;
       MyNameSpace::delete  Lsz_val;
      }
    Ensuite, il faut qualifier les opérateurs new et delete, sinonil y a ambiguîté avec les opérateurs par défaut:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    using namespace MyNameSpace;
    int main(int argc, char* argv[])
    {
     char *Lsz_val = MyNameSpace::new char;
     MyNameSpace::delete Lsz_val;
     Test();
     return 0;
    }
    Ce code compile bien et s'exécute en appelant les new et delete corrects!

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Voir ce post :

    http://www.developpez.net/forums/viewtopic.php?t=281623

    En fait ça doit dépendre des compilos.

  7. #7
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2005
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    diogene

    J'ai fait un couper/coller de ton code et j'ai les erreurs suivantes a la compilation :

    error C2834: 'operator new' must be globally qualified
    error C2834: 'operator delete' must be globally qualified

    Pour le test j'ai fait un projet Win32/Console sous Visual Studio 2003.

    Je serai vraiment interesse de savoir sous quel compilateur tu as teste ton code !

    Loulou24

    Dans le lien tu dis :
    En effet on ne peut pas, c'est indiqué dans le standard.
    Es tu sur de ca ?

    Sinon mon but est simple :
    Faire cohabiter 2 mecanismes d'allocations memoires en evitant que l'un et l'autre se telescopent. Je pourrai definir des fonctions d'allocations memoires mais c'est moins souple que les operateurs new et delete.

    ---------------------------------------------

    J'ai aussi fait le test suivant :

    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
     
    #include "stdafx.h"
     
    namespace MyNameSpace
    {
     void *New( size_t );
     void Delete( void * );
     void Test();
    }
     
    void *MyNameSpace::New(size_t size)
     {
      return malloc(size);
     }
     void MyNameSpace::Delete(void *Ppt_pt)
     {
      free(Ppt_pt);
     }
     
    void MyNameSpace::Test()
     {
      char *Lsz_val = (char *)New(255);
      Delete(Lsz_val);
     }
     
    using namespace MyNameSpace;
     
    int main(int argc, char* argv[])
    {
     char *Lsz_val = (char *)New(255);
     Delete(Lsz_val);
     
     Test();
     return 0;
    }
    Avec des fonctions simples (pas les operateurs new et delete) ca fonctionne bien, aussi bien dans Test que dans main.

    Domage que sous VC++ on puisse pas faire ca avec les operateurs new/delete.

    Merci a vous pour votre aide

  8. #8
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Je serai vraiment interesse de savoir sous quel compilateur tu as teste ton code !
    J'ai compilé et exécuté sous Borland c++Builder 5

  9. #9
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Es tu sur de ca ?
    Du tout, je ne sais absolument pas où j'ai pu aller chercher cette info . En même temps si je l'ai affirmé c'est que je l'avais vérifié. D'autant plus que Loïc ne m'a pas contredit dans sa réponse (on peut lui faire confiance concernant la norme), donc ça doit vraiment être correct.

    J'ajouterai que la solution qu'il a donnée (surcharger avec un paramètre supplémentaire) me paraît la meilleure. D'autant plus que ta solution n'est pas correcte : l'appel à new / delete appelle implicitement les constructeurs et destructeurs, ce que ne font pas tes fonctions New et Delete.

  10. #10
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2005
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Exact ! tu as raison le constructeur et destructeur ne sont effectivement pas appeles si j'utilise une fonction a la place de new et delete

    Sinon l'exemple

    class Arena;
    struct B {
    void* operator new(size_t, Arena*);
    };
    struct D1 : B {
    };
    Arena* ap;
    void foo(int i)
    {
    new (ap) D1; // calls B::operator new(size_t, Arena*)
    new D1[i]; // calls ::operator new[](size_t)
    //new D1; // illformed: ::operator new(size_t) hidden ,<--- error C2660: 'B::operator new' : function does not take 1 arguments
    }
    C'est l'operateur new de la structure (ou d'une classe) qui est redefini pas l'operateur new globale.
    Si on fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void foo(int i)
    {
      new (ap) D1;                             // calls B::operator new(size_t, Arena*)
      new D1[i];                                // calls ::operator new[](size_t)
      char *Lsz_val1 = new char[255];        // calls void *__cdecl operator new[](size_t count) from "newoap.cpp"
      char *Lsz_val2 = new (ap) char[255]; // calls inline void *__cdecl operator new[](size_t, void *_Where) from "new"
      //new D1;                                        // illformed:  ::operator new(size_t) hidden
    }
    Sinon j'ai trouve ca qui semble confirmer que normalement on ne peut pas surcharger d'operateur new et delete dans un namespace. Par contre ca date de 1999, je sais pas si la norme a evoluee depuis...
    Restrictions on Namespaces

    The C++ Standard defines several restrictions on the use of namespaces. These restrictions are meant to avert anomalies or ambiguities that can create havoc in the language.

    Namespace std Can Not Be Modified

    Generally, namespaces are open, so it is perfectly legal to expand existing namespaces with additional declarations and definitions across several files. The only exception to the rule is namespace std. According to the standard, the result of modifying namespace std with additional declarations -- let alone the removal of existing ones -- yields undefined behavior, and is to be avoided. This restriction might seem arbitrary, but it's just common sense -- any attempt to tamper with namespace std undermines the very concept of a namespace dedicated exclusively to standard declarations.

    User-Defined new and delete Cannot Be Declared in a Namespace

    The Standard prohibits declarations of new and delete operators in a namespace. To see why, consider the following

    example:

    char *pc; //global

    namespace A
    {
    void* operator new ( std::size_t );
    void operator delete ( void * );
    void func ()
    {
    pc = new char ( 'a'); //using A::new
    }
    } //A

    void f() { delete pc; } // call A::delete or //::delete?

    Some programmers might expect the operator A::delete to be selected because it matches the operator new that was used to allocate the torage; others might expect the standard operator delete to be called because A::delete is not visible in function f(). By prohibiting declarations of new and delete in a namespace altogether, C++ avoids any such ambiguities.
    Je suis pas vraiment d'accord avec leur conclusion par ce que le compilateur peut tout a fait appliquer les regles suivantes :
    - Dans les fonctions et classes du namespace => utilise l'operateur new et delete du namespace.
    - Si declaration suivante "using namespace <namespace>;" => utilise les operateurs new et delete du namespace.
    - Si new et delete sont redefinis dans plusieurs namespaces => utiliser <namespace>::new et <namespace>::delete pour lever l'embiguite.
    - Autres cas => utiliser les operateurs new/delete globaux

    S'ils pouvaient faire quelque chose comme ca ca serait vraiment cool
    En tout cas meme si les namespaces repondent pas a mes attentes je penses avoir un peu mieux compris ce qu'ils peuvent offrir.

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Effectivement dans l'exemple de Loïc il s'agit de la surcharge pour une classe précise, mais rien ne t'empêche de le faire globalement.

    A part ça, je déplace ton sujet dans le forum C++ étant donné le peu de rapport avec VC++, tu auras plus de contributions je pense.

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Tout d'abord, je confirme pour l'impossibilité de définir new et delete dans un namespace :

    Citation Envoyé par La norme du C++
    3.7.3.1 Allocation functions
    An allocation function shall be a class member function or a global function; a program is illformed if an allocation function is declared in a namespace scope other than global scope or declared static in global scope.
    Citation Envoyé par La norme du C++
    3.7.3.2 Deallocation functions
    Deallocation functions shall be class member functions or global functions; a program is illformed if deallocation functions are declared in a namespace scope other than global scope or declared static in global scope.
    Pour ce qui est de ta proposition de résolution, je pense que le problème est plus complexe. Avec la méthode que tu as proposé, dans l'exemple cité, pc sera détruit avec ::delete alors qu'il a été construit avec A::new, ce qui en général est une très mauvaise idée. Et ce genre de code ne me semble pas un cas fait exprès pour être tordu, mais une situation qui peut arriver souvent, sans que le codeur en soit tout à fait conscient.

Discussions similaires

  1. operator=(&&) à coup de placement new/delete ?
    Par germinolegrand dans le forum Langage
    Réponses: 2
    Dernier message: 29/03/2015, 14h26
  2. Surcharge de new / delete et Memory Manager
    Par LittleWhite dans le forum C++
    Réponses: 11
    Dernier message: 19/10/2010, 00h56
  3. Réponses: 18
    Dernier message: 07/10/2010, 03h18
  4. operator new sans delete
    Par babar63 dans le forum C++
    Réponses: 21
    Dernier message: 26/02/2008, 23h33
  5. intrigue sur la surcharge du new et delete
    Par swirtel dans le forum C++
    Réponses: 12
    Dernier message: 07/09/2006, 16h23

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