J'utilise boost :: make_shared Pour la première fois pour créer des objets pointés par des pointeurs partagés. Principalement parce que notre code était trop lent et que l'allocation unique a vraiment contribué à améliorer les performances.
Après avoir fixé des fuites de mémoire "The Hard Manual Way", j'ai décidé de mettre en place un détecteur de fuites de mémoire simple en remplaçant de nouveaux opérateurs pour toutes les classes pertinentes pour Compter quels objets sont toujours en vie à des points spécifiques de notre application. J'ai déjà mis en œuvre cela plusieurs fois avant et j'ai été surpris de trouver mon code ne détecte plus aucun objet. P>
J'ai pensé que tout ce que je devais faire est de remplacer "le placement nouveau" au lieu de l'opérateur "normal", car des éléments suivants de la documentation du site Web de Boost pour make_shared: P>
"Effets: alloue la mémoire appropriée pour un objet de type T et construit un objet dans celui-ci via la nouvelle expression nouvelle (PV) T () ou neuf (PV) T (STD :: AVANT (args) ...) em> strong>. allO4_shared utilise une copie de A pour allouer la mémoire. Si une exception est lancée, n'a pas effet. " p> blockQuote>
Mon placement nouveau n'est également pas appelé cependant. J'ai écrit un petit programme de test pour reproduire le comportement: p>
xxx pré> qui rend la sortie suivante: p>
xxx pré> J'étais S'attendre à ce que "test non-jetant non jetant nouveau" sur la 3ème ligne de sortie. Que pensez-vous que le comportement devrait être? Êtes-vous d'accord pour dire que, selon la documentation de make_shared, il devrait appeler le nouvel opérateur de placement de ma classe de test? Ou ai-je mal compris? P>
Je pourrais copier la mise en œuvre localement et ajouter un appel au nouvel opérateur de placement bien sûr. Mais cela serait-ce approprié ou violerait-il la sémantique envisagée du placement nouveau? P>
Merci d'avance pour votre temps et votre aide. P> P>
3 Réponses :
Vous ne pouvez pas remplacer le placement nouveau ( §18.4. 1.3 em>, voir par exemple Cette question a >), donc la sortie donnée semble bien. p>
Autre alternative à la modification des en-têtes de boost, vous pouvez examiner des outils externes tels que Valgrind. P>
En regardant comme source de Malheureusement EDIT STRY>: P> Une alternative pourrait être d'écrire une version de make_shared code>, il utilise l'opérateur de placement global de placement
nouveau code>, au lieu du nouvel opérateur fourni par votre classe.
(au moins sur OS X) Strike> ( selon la norme ), vous ne peut pas définir votre propre nouveau opérateur de placement global. Il semble que allOCate_shared code> a > est plus dans les lignes de ce que vous recherchez. p>
make_shared code> qui utilise le placement de la classe neuf au lieu de la mondialisation. Ce n'est qu'environ 10 lignes de code et devrait aller aussi longtemps que vous honorez La licence du code d'origine < / a>. p> p>
Ça vaut la peine de noter que allOCate_shared () code> pourrait signifier remplacer plusieurs appels dans une générosité plus importante.
Merci pour la réponse utile. Je ne savais pas que je n'étais pas censé remplacer le placement nouveau. Donc, c'est certainement un showstopper pour ma tentative d'une solution. J'ai déjà enquêté sur l'option Allocate_shared, mais -as Georg a déclaré: cela a un impact trop élevé sur le code existant.
Votre opérateur Il utilise ensuite placement-nouveau em> pour appeler le constructeur de votre objet. Notez que le placement nouveau em> dans ce cas ne correspond pas à la mémoire, ce n'est que la syntaxe amusante en C ++ pour appeler le constructeur sur un bloc de mémoire déjà allouée. Cela pourrait en réalité être la source de confusion, comme l'expression Nouveau code> implémenté pour votre type particulier ne sera utilisé que sur les expressions sur lesquelles les éléments de votre type sont alloués de manière dynamique em> avec
neuf code>, telle que
test * p = nouveau test; code>. Maintenant,
make_shared code> n'est pas allouer de manière dynamique em> un objet de votre type, mais plutôt un tampon em> qui contient suffisamment d'informations pour le compte partagé EM> (qui inclut le compteur, le Deleter et quelques bits et morceaux supplémentaires) et votre objet. p>
nouvelle code>, votre
Opérateur neuf code> et placement-nouveau em> sont trois concepts différents qui se produisent un nom. p>
Malgré cela, il est toujours possible de fournir une surcharge par classe, même pour le placement nouveau. Peu de temps peut-être, mais encore une fois, quelle partie de C ++ n'est pas i> insolite :-) Le point principal à ramener est que std :: allocator code> n'utilise aucun par -Class Fonctions d'allocation, mais seulement le global
:: nouveau code>.
En regardant Boost's, il utilise le nouvel opérateur de placement global :: Nouveau (PV) T (). C'est pourquoi votre placement de niveau de classe n'est pas appelé ... en supprimez le qualificatif global '::' Avant nouveau, le make_shared appelle en fait votre ancien opérateur de placement de niveau de classe.