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 :

[Mémoire] Alignement de mémoire et new/delete


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut [Mémoire] Alignement de mémoire et new/delete
    Bonsoir à tous !

    J'ai besoin que ma mémoire soit aligné, et pour ceci j'utilisais _mm_malloc et _mm_free. Toutefois, après avoir cherché pendant pas mal de temps ce qui causait un problème dans mon problème, je me suis rendu compte que malloc et free n'appelaient pas le constructeur et... ben c'est pareil pour _mm_malloc et _mm_free.

    J'ai essayé d'utiliser le code ici (http://www.swedishcoding.com/2008/08...out-of-memory/), que je recopie ici :

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    class Align
    {
    	public:
    		explicit Align (std::size_t value_)
    			: value (value_)
    		{
    		}
     
    		std::size_t GetValue () const
    		{
    			return value;
    		}
     
    	private:
    		std::size_t value;
    };
     
     
    // Surcharge de l'opérateur new (normal)
    static void * operator new (std::size_t size_)
    {
    	return malloc (size_);
    }
     
     
    // Surcharge de l'opérateur delete (normal)
    static void operator delete (void * memory_)
    {
    	free (memory_);
    }
     
     
    // Surcharge de l'opérateur new pour les tableaux (normal)
    static void * operator new [] (std::size_t size_)
    {
    	return malloc (size_);
    }
     
     
    // Surcharge de l'opérateur delete pour les tableaux (normal)
    static void operator delete [] (void * memory_)
    {
    	free (memory_);
    }
     
     
    // Surcharge de l'opérateur new (aligné)
    static void * operator new (std::size_t size_, Align alignment_)
    {
    	return _mm_malloc (size_, alignment_.GetValue());
    }
     
     
    // Surcharge de l'opérateur delete (aligné)
    static void operator delete (void * memory_, Align alignment_)
    {
    	_mm_free (memory_);
    }
     
     
    // Surcharge de l'opérateur new pour les tableaux (aligné)
    static void * operator new [] (std::size_t size_, Align alignment_)
    {
    	return _mm_malloc (size_, alignment_.GetValue());
    }
     
     
    // Surcharge de l'opérateur delete pour les tableaux (aligné)
    static void operator delete [] (void * memory_, Align alignment_)
    {
    	_mm_free (memory_);
    }
    Pour les versions "normales", ça marche bien, mais pour les versions alignées, problème.

    La mémoire est correctement allouée, en faisant soit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Foo * foo = new (Align(8)) Foo; // Un seul élément
    Foo * foo = new (Align(8)) Foo [4]; // Tableau
    Par contre, cela pose un soucis pour la libération de la mémoire. Car si j'écris delete (Align(16)) foo; ou delete[] (Align(16)) foo; ceci ne fonctionne pas...

    J'ai également essayé operator delete [] (foo, Align(16)), et la bonne fonction est bien appelée mais j'obtiens un crash (Damage before 0x00083E58 which was allocated by aligned routine), comme si la mauvaise adresse était passée....

    Si quelqu'un a un moyen de résoudre ce soucis je prends !!


    Et j'ai une autre petite question ! Par exemple, si j'écris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Foo * foo = new (Align(16)) Foo[4];
    La bonne fonction est bien appelée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    static void * operator new [] (std::size_t size_, Align alignment_)
    {
    	return _mm_malloc (size_, alignment_.GetValue());
    }
    Par contre j'ai remarqué que size_ est plus grand que prévu. Exemple, si sizeof (Foo) = 8 octets, j'obtiens size == 40 octets au lieu de 8. Est-ce que le compilo alloue 4 octets pour quelque chose de spécial (la taille j'imagine ?).

    Mirci !

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

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Bonsoir,
    Pour ton erreur sur le delete, je ne crois pas qu'il faille appeler delete avec Align. Le delete par placement n'appelle pas le destructeur, donc un delete avec des arguments en plus ne le fait peut-être pas non-plus. Dans tout les cas, un delete ordinaire semble suffire.
    (Les delete avec Align n'existe que pour le cas ou le new générerai une exception. Dans ce cas le compilateur appel un delete qui a les meme argument que le new.)

    Pour ta question sur les 4 octet en plus. Je pense que cela dépend du compilateur mais je dirait qu'il doit y avoir 4 octets en plus pour savoir le nombre d'objet alloué. Pour pouvoir détruire le même nombre d'objet lors du delete.

    [EDIT]
    Je ne sait pas ce que tu compte faire avec ce new et delete surchargés, mais tu risque d'avoir des problèmes avec toutes les class qui utilisent des new et delete dans leurs fichier d'entête, comme par exemple les std::vector. Car tu va surcharger le delete mais pas le new(qui n'as pas le même prototype), et tu risque d'utiliser mm_free sur de la mémoire allouée avec new.

  3. #3
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Dans tout les cas, un delete ordinaire semble suffire.
    Non. La mémoire allouée avec _mm_malloc doit être obligatoirement libérée avec _mm_free. D'ailleurs, si j'alloue la mémoire avec _mm_malloc et que j'appelle delete [] foo, il va appeler la version normale du delete, et m'indiquer un message d'erreur comme quoi la mémoire allouée avec l'alignement doit être libérée avec _mm_free.

    Je ne sait pas ce que tu compte faire avec ce new et delete surchargés, mais tu risque d'avoir des problèmes avec toutes les class qui utilisent des new et delete dans leurs fichier d'entête, comme par exemple les std::vector.
    Pourquoi ça ? std::vector utilisera les surcharges "normales" de new, non ?


    En fait, pour être honnête, j'aimerais beaucoup pouvoir me passer des pointeurs. Le seul soucis, c'est que std::vector ne permet pas d'aligner la mémoire. Après avoir cherché un peu sur Google, visiblement c'est un des problèmes de la STL actuelle... Mais si quelqu'un a une solution portable et pas trop compliquée pour pouvoir utiliser les vector avec la mémoire alignée, je suis preneur aussi :p.

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Salut.
    Il te faut redéfinir new et delete dans ta class

    http://www.ann.jussieu.fr/courscpp/S...Sect07-B9.html

  5. #5
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Je pense que je vais faire ça, ça va être moins prise de tête. Et concernant vector ?

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Bakura Voir le message
    Je pense que je vais faire ça, ça va être moins prise de tête. Et concernant vector ?
    Il utilise l'allocator qu'on lui donne en parametre template.
    Donc je suppose qu'il redéfinie ses new et delete

  7. #7
    Membre expérimenté Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Citation Envoyé par Bakura Voir le message
    Dans tout les cas, un delete ordinaire semble suffire.
    Non. La mémoire allouée avec _mm_malloc doit être obligatoirement libérée avec _mm_free. D'ailleurs, si j'alloue la mémoire avec _mm_malloc et que j'appelle delete [] foo, il va appeler la version normale du delete, et m'indiquer un message d'erreur comme quoi la mémoire allouée avec l'alignement doit être libérée avec _mm_free.
    Attention, par "delete ordinaire" je fait référence au delete surchargé mais ne prenant pas d'argument en plus. C'est d'ailleurs ce qui est fait dans le lien que tu as donné dans ton premier message.
    En revanche je suppose qu'il utilise le _mm_malloc dans ces 4 operateurs new. (mais je n'est pas trouvé le contenu de ces new donc je n'ai aucune certitude)

    std::vector utilisera les surcharges "normales" de new, non ?
    En fait j'ai déjà eu ce problème, en surchargeant new pour y passer _FILE_ et _LINE_. Le vector appelait le new normal, mais mon delete a moi...

  8. #8
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Une petite précision apportée par les gurus de Ompf, lorsque j'ai posté ta solution Charlemagne :

    Well, yes, this avoids segfaults at run time by taking care memory is properly allocated, but you still need to patch your STL if you're using Visual Studio, because there the problem is a compile time error and a problem with the compiler itself.

    This :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main(int argc,char *argv[])
    {
       std::vector<__m128, AlignmentAllocator<__m128, 8> > foo;
       foo.resize(222);
       return 0;
    }
    Segfaults when run with msvc9. (But gives no warning messages when being built.)

  9. #9
    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
    D'un autre côté, qu'un type SIMD de 16 octets plante lorsqu'on lui donne un alignement de 8, ça ne me choque pas particulièrement...
    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.

  10. #10
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Effectivement, cela ne me choque pas non plus (en fait j'avias pas vu que le gars avait écrit 8), mais d'après ce que j'ai compris de leur message, ça planterait même avec 16... A tester :p.

  11. #11
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    operator new est censé allouer la mémoire avec un alignement suffisamment important pour tous les types.
    C'est un design totalement stupide à mon avis, d'autant plus que le type et donc l'alignement sont connus quand on utilise new.

    La solution la plus pratique reste de surcharger operator new et operator delete pour ton type, puisque c'est totalement non intrusif...
    std::allocator alloue sa mémoire avec ces opérateurs, donc pas de soucis.

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

Discussions similaires

  1. new/delete/cast, fuite de mémoire ou pas ?
    Par boli_971 dans le forum C++
    Réponses: 7
    Dernier message: 18/04/2009, 13h40
  2. Réponses: 3
    Dernier message: 04/12/2006, 15h19
  3. tableau de pointeurs et new, delete
    Par luckydigit dans le forum C++
    Réponses: 12
    Dernier message: 21/07/2006, 11h24
  4. [Débutant]Constructeur et new/delete
    Par Geolem dans le forum C++
    Réponses: 5
    Dernier message: 02/12/2005, 21h11
  5. Namespace et surcharge operator new/delete
    Par ZeLegolas dans le forum C++
    Réponses: 11
    Dernier message: 26/07/2005, 13h55

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