5 votes

surcharge des opérateurs new et delete pour dll

Comment surcharger new y delete pour un dll . J'ai écrit des opérateurs surchargés en tant que partie de la dll, mais le client se lie avec ceci dll n'utilise pas overloaded new and delete

9voto

Mikael Persson Points 7174

Voici ce que dit la norme C++ à ce sujet, dans la section 17.6.4.6/3 :

Les définitions du programme (des opérateurs de création et de suppression) sont utilisées au lieu des versions par défaut fournies par l'implémentation. Ce remplacement a lieu avant le démarrage du programme. Les définitions du programme ne doivent pas être spécifiées en tant que inline . Aucun diagnostic n'est nécessaire.

Si vous lisez attentivement ce texte, il explique exactement le problème que vous rencontrez. Il y a une sorte de "catch 22" qui se produit ici.

D'une part, vous ne pouvez pas avoir les définitions de vos opérateurs new/delete compilées à l'intérieur de la DLL parce que les new/delete surchargés ne peuvent pas être liés dynamiquement (ceci parce que new/delete pourrait être nécessaire pendant l'initialisation statique, avant le chargement de la DLL, donc vous auriez des opérateurs new/delete incohérents avant et après le chargement de la DLL, et c'est un comportement indéfini).

D'un autre côté, vous ne pouvez pas simplement placer vos définitions d'opérateurs de type "new/delete" dans vos fichiers d'en-tête de DLL, car elles devraient être marquées inline afin de satisfaire à la règle de la définition unique (ODR), qui, à son tour, ne satisfait pas à la clause ci-dessus. L'exigence selon laquelle ils ne doivent pas être marqués inline est probablement là parce qu'une définition de fonction marquée inline n'a pas de lien, ce qui fait que chaque unité de traduction utilise sa propre version compilée (ou des expansions en ligne), ce qui est normalement acceptable, mais pas pour l'allocation dynamique de mémoire.

Les deux captures ci-dessus sont motivées par le fait que, pour être correct, il faut généralement garantir que la mémoire allouée à l'aide de new est désallouée avec l'objet correspondant delete (c'est-à-dire "compilées ensemble", pour ainsi dire, ou toutes deux par défaut). Par exemple, si vos opérateurs new/delete s'appuient sur un appel malloc/free sous-jacent, vous vous appuyez sur le tas utilisé par l'unité de traduction qui a appelé l'opérateur new/delete, entre une DLL et un exécutable, rien ne garantit que ce tas sera le même (en fait, sous Windows, en particulier, il ne l'est pas, les deux modules utilisent deux tas distincts pour les allocations de mémoire dynamique).

Donc, la solution à votre problème, comme le dit Rook, est "ne faites pas ça". Ne surchargez pas les opérateurs new/delete pour les objets DLL parce qu'il n'y a pas de méthode propre pour le faire correctement, quelle que soit la façon dont vous tournez et tournez votre code, il se résumera toujours au même problème mentionné ci-dessus.

Ce que vous pouvez et devez faire à la place, c'est utiliser un modèle de fonction d'usine pour vos objets DLL et renvoyer un pointeur intelligent (tel qu'un fichier std::shared_ptr ) avec un suppresseur personnalisé qui s'appuie sur une répartition dynamique de la suppression vers le site où l'objet a été créé. Ceci est inspiré d'une technique de Chad Austin . J'ai fait quelque chose de très similaire ici .

0voto

Daniel McCarthy Points 17

Vous pouvez essayer d'écrire vos propres fonctions malloc et delete, puis créer une définition C qui contient essentiellement le code permettant de remplacer new et delete et d'appeler ces fonctions malloc et delete personnalisées.

De cette façon, vous pourriez faire quelque chose comme

MODULE_START()
// CODE HERE

MODULE_END()

et cela devrait fonctionner sans problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X