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 :

Redéfinition opérateurs new et delete globaux


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut Redéfinition opérateurs new et delete globaux
    Bonsoir tout le monde,

    en suivant le tutoriel sur la conception des moteurs 3D de Laurent Gomilla, j'ai eu un problème avec le gestionnaire de mémoire. Celui-ci redéfinit les opérateurs new et delete de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    inline void* operator new(std::size_t size, const std::string& file, int line)
    {
        return memorymanager::MemoryManager::GetInstance().allocate(size, file, line);
    }
     
    ...
    //code similaire pour les autres opérateurs
    La fonction (static) pour récupérer l'instance de MemoryManager :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    MemoryManager& MemoryManager::GetInstance()
    {
        static MemoryManager Instance;
        return Instance;
    }
    Le problème est que le MemoryManager contient une map et une stack comme attributs de classe, et que pendant l'initilisation de la map, un opérateur delete est appelé ; la variable Instance n'étant pas initialisée, il rappelle le constructeur et ça boucle infiniment.

    Je cherche une astuce qui me permettrait de prendre en compte les opérateurs redéfinis une fois le MemoryManager initialisé.

    Merci d'avance.

  2. #2
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Utiliser un flag que tu mets à true une fois l'allocateur initialisé ?

  3. #3
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Dans le code je fais en sorte que ces surcharges ne soient justement pas prises en compte lors de la définition du gestionnaire de mémoire (en n'incluant pas l'en-tête qui les définit).

  4. #4
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Deja merci pour vos reponses

    Le fait est que je n'inclue pas la definition des operateurs dans le fichier de definition du gestionnaire de memoire. Du coup au moment de l'initialisation, lorsqu'un operateur new est appele, pas de probleme, il appelle bien l'operateur standard, par contre pour les appels a delete, il appelle bizarrement celui redefinit.

    Ca marche effectivement en passant par un flag, bien que je ne trouve pas la solution tres elegante, mais bon a defaut de trouver mieux je vais faire comme ca :/

    En tout cas je ne comprends pas pourquoi il utilise les operateurs delete redefinis meme la ou l'entete DebugNew.h n'est pas inclue.

    P.S. : desole pour les accents, clavier qwerty du boulot.

  5. #5
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Citation Envoyé par bolhrak
    En tout cas je ne comprends pas pourquoi il utilise les operateurs delete redefinis meme la ou l'entete DebugNew.h n'est pas inclue.
    Honêtement je n'ai jamais compris non plus.

    Certains diront sûrement que ce genre de solution est "crade"; je suis globalement d'accord avec eux mais je n'ai jamais trouvé de solution de rechange qui soit aussi satisfaisante.

  6. #6
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Bon ayant ressorti ma bonne vieille bible et ayant mis un peu plus les mains dans le camboui j'en arrive à d'autres questions sur le fonctionnement interne de ces opérateurs. Je préfère éviter de polluer le forum et continuer dans ce topic déjà résolu.

    Donc ma première question : un appel à new pour la construction d'un objet :
    va générer un appel à l'opérateur new de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ::operator new(sizeof(X))
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    X::operator new(sizeof(X))
    dans le cas de la redéfinition de cet opérateur pour la classe X. Or l'opérateur new retourne par définition un void* et le casting implicite d'un void* est interdit. Donc que se passe-t-il exactement ?

    Deuxièmement, l'operator new se contente d'allouer de la mémoire sans l'initialiser, pourtant un objet construit via la ligne de code précédente est initialisé. Ma première intuition était que l'initialisation était effectuée une fois le pointeur retourné (qu'en fait l'appel a l'opérateur new se contentait de retourner le bloc de mémoire et que l'affectation à un objet de type X appelait le constructeur). Le problème est que cela ne colle pas avec un constructeur demandant des arguments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    X* p = new X(integer, float)
    Je continue avec une petite question concernant l'opérateur new de placement et la destruction des objets alloués de cette manière. Pour la partie allocation, dans le cas de l'opérateur new de placement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void* operator new(size_t size, void* p) {return p}
    où se trouve l'allocation de mémoire ? Cet opérateur ne fait que retourner un bloc de mémoire passé en paramètres. Question subsidiaire, cet opérateur est généralement utilisé de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    void* buf = reinterpret_cast<void*>(0xF00F)
    X* p = new(buf) X;
    Comment est-on sûr que l'adresse passée en paramètre de l'opérateur :
    1) est valide ?
    2) est allouée ?

    Pour la partie destruction, pourquoi un appel à l'opérateur delete ne peut être effectué sur un objet alloué de cette manière ? Dans la mesure où l'opérateur delete prend en argument le pointeur (donc l'adresse de l'objet), et où l'opérateur new de placement retourne le pointeur sur la zone mémoire contenant l'objet où est le problème ?

    Enfin pour l'opérateur delete comment l'appel au destructeur est-il possible ? Cet opérateur prend un void* en paramètres ; de plus en redéfinissant cet opérateur de manière à ce qu'il se contente de libérer la mémoire via un appel a free, si l'on définit une hiérarchie de classe, on constate que les destructeurs des classes de base d'un objet sont quand même appelé. Comment cela peut-il se produire sans que cela ne soit codé explicitement, et surtout sans que l'opérateur delete ne connaisse ne serait-ce que le type de base de l'objet à détruire (cas dans lequel je comprendrais que cela est possible via la table de fonctions virtuelles) ?

  7. #7
    Invité de passage
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1
    Par défaut Solution propre
    Le problème de la récursivité proviens en fait du std::stack. Je remplace simplement la std::stack par un std::vector. Du coup il faut remplacer les

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    m_DeleteStack.top() par m_DeleteStack.back()
     
    m_DeleteStack.pop() par m_DeleteStack.pop_back();
     
    m_DeleteStack.push(Delete) par m_DeleteStack.push_back(Delete);
    Voila, normalement tout s'execute normalement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. opérateurs new et delete sous gcc, je comprends pas.
    Par Guyt54 dans le forum Embarqué
    Réponses: 5
    Dernier message: 07/08/2012, 17h56
  2. opérateur new et delete, je comprends pas
    Par Guyt54 dans le forum Langage
    Réponses: 4
    Dernier message: 25/07/2012, 16h55
  3. Redéfinition de l'opérateur new
    Par Khan34 dans le forum C++
    Réponses: 15
    Dernier message: 05/07/2012, 16h27
  4. Surcharge de l'opérateur new
    Par :Bronsky: dans le forum C++
    Réponses: 17
    Dernier message: 27/10/2010, 21h33
  5. namespace et opérateur new
    Par Sylvain Rousseau dans le forum C++
    Réponses: 3
    Dernier message: 06/01/2005, 23h24

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