J'ai créé un allocator personnalisé qui alloue la mémoire sur la construction et la libérule sur la destruction. (Afin de permettre une allocation rapide / une distribution de distribution). Quand je l'utilise avec un conteneur stl, tout fonctionne bien! Attendu quand j'utilise la méthode d'affiliation ... Je ne comprends pas pourquoi ...
J'ai essayé d'imprimer chaque pointeur alloué / libre, mais tout va bien. P> effectivement le crash de programme.
Si je commente 'conteneurb.Assign (10, i);', le programme fonctionne.
Si je remplace 'conteneurb.Assign (10, i);' par 'conteneurb.emplace_front ();', le programme fonctionne.
Si je remplace 'conteneurb.Assign (10, i);' par 'conteneurb.insert (conteneurb.begine (), 10, i);', le programme de programme.
Je ne comprends pas pourquoi ... p> Erreur avec Clang et GCC:
GRATUIT (): Correction des morceaux non triés corrompus
Abort (noyau largué) p> erreur avec gdb:
GRATUIT (): corrompu des morceaux non triés (P> Signal reçu Sigabrt, abandonné.
__Gi_rise (SIG = SIG @ Entry = 6) à ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: Aucun fichier ou répertoire de ce type. P> mise à jour: p> avec meilleur opérateur ==, j'ai maintenant un SIGSEGV:
Signal reçu du programme SIGSEGV, défaut de segmentation.
0x000055555555537A dans STD :: __ CXX11 :: _ LIST_BASE> :: _ m_clear (ceci = 0x7FFFFFDCD0) à /usr/include/c++/8/bits/list.tcc:74
74 __Cur = __tmp -> _ m_next; p> la sortie Valgrind: p>
3 Réponses :
Selon la norme, pointeur arithmétique sur EDIT FORT> m_data code> est un pointeur sur
void code>. Il y a le pointeur arithmétique effectué sur
m_data code> dans le constructeur de
Customallocator code> dans la ligne suivante.
void * code> est mal formé. Cela pourrait conduire à un comportement indéfini. P>
L'OP a été mis à jour et il n'y a plus d'arithmétique de pointeur effectué sur un void * code>. Nous devons donc trouver d'autres causes pour le crash.
Pour Liste Code> Container
EMPECE_FRONT CODE> n'affecte pas la validité des itérateurs et des références. Mais les deux
assigner code> et
effacer code> invalident toutes les références, les pointeurs et les itérateurs faisant référence aux éléments du conteneur.
Donc, le programme fonctionne avec emplace_front code> et qui se bloque avec
assignez code>. P> p>
@ DJ4567: édité la réponse en conséquence, offrant une raison éventuelle de l'accident.
Oui, j'ai lu. L'assignation est toujours effectuée sur un conteneur vide, car pour chaque boucle, le conteneur est effacé. Je ne comprends donc pas pourquoi: / Le code est simple et j'ai passé beaucoup de temps à déboguer cela ... c'est bizarre. Lorsque j'appelle la méthode d'attribution, le code appelle le constructeur d'allocator, j'ai trouvé cela bizarre. Pourquoi la méthode d'affectation crée-t-elle un nouvel allocator? : O
Si je remplace 'conteneurb.Assign (10, i);' par 'conteneurb.insert (conteneurb.begine (), 10, i);', il ne fonctionne pas. Donc, le problème ne provient pas d'itérateur ou de référence invalidée, puisque INSERT MATY n'a pas annulé Itérateur et référence.
@ DJ4567: Il semble qu'il y ait plus de problèmes dans votre code. J'ai essayé de déboguer et j'ai constaté que les destructeurs étaient appelés avant même que les boucles code> pour code> ont été exécutées. Voir ceci: wandbox.org/permlink/isfklte5ut8pqwic . Et ils sont appelés plus tard aussi.
Oui, car STD :: Liste Créez un nouvel allocator afin de transformer Customallocator
Maintenant, dans le code mis à jour, si je commente le :: L'opérateur Supprimer dans le destructeur, tous les travaux. Sinon, j'obtiens un SIGSEGV ... c'est très étrange!
Regardez ceci: la méthode de distribution est appelée avec un PTR bizarre: wandbox.org/permlink/ysgo6nbdpn6ryJPK Que faire Vous pensez à cela? Peut-être: l'allocator se compare égal, la liste utilise donc un allocator pour annouez un pointeur attribué à l'autre allocator. Plus tard, l'allocator est supprimé de sorte que l'autre allocateur a un pointeur pendant? Conclusion: L'allocator de la piscine ne fonctionne pas avec STL? Je ne sais pas ... Si vous avez une meilleure idée ....
Regardez aussi ceci: wandbox.org/permlink/zwsm8pihicrofs9s Je ne sais pas comment résoudre ce problème: o Tous les allocateurs depuis C ++ 11 peuvent avoir un état. p>
Mais tous les allocateurs ont été copiés du même État d'allocator partagé, de sorte que quelque chose attribué par l'allocator d'origine devrait annoncer une copie optimale. P>
aussi opérateur == et opérateur! = Devrait comparer l'état, les allocateurs ne doivent pas être égaux si l'état est différent. p>
Ceci peut être mis en œuvre en ayant un pointeur sur une piscine potentiellement partagée dans votre allocateur plutôt que directement d'avoir une piscine dans l'allocateur. (La piscine d'allocator partagée est parfois appelée «arène»). P>
Avant C ++ 11, les allocateurs n'ont pas pu le faire. Pour que les objets puissent être alloués / distribués, même avec un allocator construit par défaut, ce qui peut être un exemple différent à chaque fois. Dans ce cas, vos opérateurs d'égalité sont corrects, mais vous devez disposer d'une piscine globale plutôt que de possibilité de piscine séparée pour chaque conteneur. P>
Je peux mettre le vide * et empiler dans une structure et gérer un pointeur sur cette structure?
Oui, tant que différentes copies du même allocator accéderaient à la même structure.
Mais un allocator
Oui, les allocateurs de différents types peuvent ne pas avoir de struct partagé, car la structure allouée par l'allocator
Dans ce cas, j'ai besoin d'une sorte de carte mondiale qui contient chaque piscine pour chaque type ... mais étant donné que l'allocator multiple de T utilisera la même piscine T, j'ai 2 options: 1 / Ajouter un mutex dans la piscine partagée, Mais dans ce cas, l'efficacité de la piscine est perdue ... de sorte que la piscine devienne inutile. 2 / Gardez un coffre-fort non du fil, mais dans ce cas, je ne peux pas utiliser plusieurs allocator
Si votre compilateur / stl est compatible C ++ 11, l'allocator peut avoir un état. Donc, deux instances d'allocator
Avant C ++ 11, vous auriez vraiment besoin d'utiliser la piscine par type.
Et si vous avez C ++ 17, vous n'avez même pas besoin de mettre en œuvre votre propre allocator. Vous venez d'implémenter votre piscine en héritant
J'utilise C ++ 17, et je connais le Memory_Resource. Mais j'ai un problème avec la ressource de mémoire. Actuellement, j'ai une piscine d'objet (par exemple, une piscine de taille_t, une piscine de char). Je voudrais utiliser un Memory_Resource mais je ne peux pas. Le constructeur de copie de std :: polymorphic_allocator (utilisé avec STD :: Memory_Resource) Do: construit un polymorphic_allocator à l'aide d'autres.Resource () comme la ressource de mémoire sous-jacente. Dans ce cas, je ne peux pas avoir une piscine comme celle-ci. Pour utiliser le Memory_Resource, le Memory_Resource peut permettre à toutes les tailles (mon pool actuel ne peut affecter que la taille d'un type).
Un polymorphic_allocator
Oui. Ensuite, vous ne devriez pas utiliser Memory_Resource. En fait, j'ai compris que c'était trompeur de dire "Cela peut être mis en œuvre en ayant un pointeur pour potentiellement piscine partagé dans votre allocateur plutôt que d'avoir directement une piscine dans l'allocator". Oui, il est couramment fait, mais vous n'êtes pas obligé de le faire. Comme vous avez défini Après cette discussion, j'ai mis en place un alloator Stateful, mais j'ai un problème avec STD :: Liste.
J'ai posté une question à ce sujet: conteneur STL ne prend pas en charge l'allocator Stateful? p> >. Nous avons donc du constructeur de copie et déplacez le constructeur appelé. J'ai mis à jour mon code, maintenant j'ai une faute de segmentation au lieu d'un Sigabrt. Je suppose que STD :: Liste n'aime pas l'itérateur qui n'est toujours pas égal, j'ai donc mis à jour l'opérateur ==. Je ne vois aucune chose étrange dans mon code ... je ne comprends pas :(
votes
std :: pmr :: memory_resource code> et transmettez-le aux conteneurs qui utiliseraient
std :: pmr :: polymorphic_allocator code>. Les conteneurs avec cet allocator sont disponibles dans l'espace de noms STD :: PMR.
propagate_on_container _ * code> traits to faux_type, vous pouvez avoir une piscine directement dans l'allocator. Néanmoins, vous devrez corriger == et! = Opreacteurs, ils doivent être égaux que si l'instance est égale, pas de typeid.
votes
Crash comme dans? Jeter une exception?
FYI,
void code> pour
t code> dans votre
Taille_t code> Argument Constructeur aboutit à un comportement plus optimiste. Ces mêmes problèmes se produisent ailleurs. Je suis franchement choqué que votre compilateur ne ressort pas des avertissements (qui devraient être traités comme des erreurs) à vous, car le mien le fait certainement.
J'ai remplacé le pour par: pour (auto ptr = static_cast (m_data) + (taille - 1); PTR> = statique_cast (M_DATA); PTR--) M_FREE.PUSH (PTR) ; Mais ne fonctionne pas.
Le programme Crash: Sigabrt
Avez-vous essayé de déboguer, par exemple pour voir comment votre allocation et vos fonctions d'affectation sont réellement appelées? Ou courir sous un outil comme Valgrind?
Valgrind Détection Aucune fuite et Résultat GDB est le suivant: Signal de programme reçu Sigabrt, avorté. __Gi_rise (SIG = SIG @ Entry = 6) à ../sysdeps/unix/sysv/linux/raise.c:51 51 ../sysdeps/unix/sysv/linux/raudise.c: Aucun fichier ou répertoire de ce type. J'ai ajouté une impression dans chaque méthode / constructeur / destructeur, le programme ne collez pas dans la fonction d'allocator.