Je travaille sur un petit outil de mémoire qui suit les allocations et les désallocations, les tailles d'objets, les types d'objets, etc. La méthode que je vais utiliser pour le suivi des fichiers sources, les numéros de ligne et les types d'objets fonctionne comme ceci:Problème d'interception et de collecte d'objets/d'objets lorsque l'utilisateur appelle l'opérateur nouveau
#define DEBUG_NEW SourcePacket(__FILE__, __LINE__) * new
#define new DEBUG_NEW
SourcePacket est juste une petite classe qui prend un const char * et un int pendant la construction. Ces valeurs sont renseignées via les macros __FILE__
et __LINE__
. Le type d'objet est acquis comme ceci:
template<typename T>
T* operator*(const SourcePacket& packet, T* p);
p est le pointeur sur l'objet nouvellement affecté, dont le type est découvert en utilisant RTTI. Dans la surcharge de l'opérateur, les informations sont prises et stockées dans le traceur et le pointeur est transmis au programme. D'autres informations comme la taille et l'adresse sont saisies dans l'opérateur surchargé.
Maintenant, cette configuration a très bien fonctionné pour moi. Il ne fonctionne pas pour le code que je ne compile pas, naturellement, mais l'une des meilleures choses est qu'il joue bien avec le placement de nouveaux appels effectués par l'utilisateur, qui ne fonctionne pas à l'aide de la cité souvent
#define new new(__FILE__, __LINE__)
méthode. Le problème que j'ai rencontré est que si l'utilisateur appelle l'opérateur new, le programme ne peut tout simplement pas compiler. Bien sûr, cela est parce que la macro se développe comme si
return operator SourcePacket("blahblah.cpp", 20) * new(size);
au lieu de
return SourcePacket("blahblah.cpp", 20) * new(size);
Je ne peux pas vraiment voir une façon de contourner cela. Je pourrais, bien sûr, juste enlever la nouvelle procédure SourcePacket * et juste laisser mon nouvel opérateur surchargé recueillir la taille et l'adresse, mais ce genre de défaites une grande partie de l'objectif de l'outil.
(De même, je ne cherche pas à créer Valgrind ou quoi que ce soit d'autre, et je sais que surcharger les opérations globales peut être plutôt douteux, surtout à des fins éducatives. Des fonctionnalités spécifiques peuvent être utilisées pour découvrir certaines de ces informations, mais je voudrais seulement utiliser le C++ standard pour qu'il soit multi-plateforme et indépendant des bits (x86, x64, etc.). Malheureusement, il ne semble pas y avoir de moyen d'utiliser l'un ou l'autre de façon conditionnelle, selon qu'il s'agit simplement d'un nouveau (ou d'un nouvel emplacement) ou d'un nouvel emplacement. opérateur nouveau. Ce n'est pas critique que je fais fonctionner cela, mais je serais intéressé d'entendre si quelqu'un a trouvé un moyen de contourner cette limitation.
Merci pour cette réponse détaillée outis! Je pense que j'obtiens ce que tu vis, mais je dois admettre que je ne suis pas sûr d'avoir compris l'essentiel. Avant votre modification, j'ai trouvé que le changement de macro faisait que le compilateur se plaignait d'une erreur de syntaxe en point-virgule, mais le problème semble plus grand que cela. Une chose qui me harcèle en passant par ce problème est qu'en insérant l'opérateur unaire dans le mix et en ajoutant la configuration commutative pour gérer correctement l'expression, l'intention de l'énoncé pourrait changer - cela pourrait finir par changer un opérateur. "appeler dans une" nouvelle "opération normale. – Gemini14
Notez que si les appels à 'new' apparaissent seulement du côté droit des affectations et des expressions entre parenthèses, vous n'aurez pas besoin de traiter l'associativité gauche de' * ', ce qui simplifie grandement les choses. En ce qui concerne la perte de 'operator', vous pourrez peut-être bricoler quelque chose basé sur deux' new' surchargés plutôt que sur le unary '*' (vous pourriez aussi avoir besoin de laisser tomber le 'SourcePacket' et utiliser simplement' new'). Je suis allé avec '*' parce que c'était plus simple, et j'avais des problèmes avec 'new'. – outis
Je suppose qu'il n'y a pas moyen de couvrir tous les cas, car les macros C++ ne sont pas capables de gérer des expressions complexes. Franchement, j'ai été surpris de pouvoir faire fonctionner ce qui précède. – outis