2009-02-24 2 views
19

Je fais un peu de recherche de fuite de mémoire dans mon programme, mais ma façon de surcharger nouveau et supprimer (et aussi nouveau [] et supprimer []) ne semble pas faire quoi que ce soit.surcharger nouveau/supprimer

void* operator new (unsigned int size, const char* filename, int line) 
{ 
    void* ptr = new void[size]; 
    memleakfinder.AddTrack(ptr,size,filename,line); 
    return ptr; 
} 

La façon dont je surchargée new est représentée dans l'extrait de code ci-dessus. Je suppose que c'est quelque chose avec l'opérateur qui retourne le vide * mais je ne sais pas quoi faire à ce sujet.

+6

"ne semble rien faire": que voulez-vous dire? Vous avez surchargé l'opérateur, mais vous n'avez pas * remplacé * l'opérateur par défaut new, donc "new x" appelle le nouveau par défaut alors que "new (filename, line) x" appelle votre version surchargée. –

Répondre

11
void* ptr = new void[size]; 

Impossible de faire cela. Répare le.

Ne jamais essayer de surcharger nouveau/supprimer globalement. Vous pouvez les avoir dans une classe de base et dériver tous vos objets de cette classe ou utiliser un espace de noms ou un paramètre d'allocateur de modèle. Pourquoi, vous pouvez demander. Parce que dans le cas où votre programme est plus d'un seul fichier et en utilisant STL ou d'autres bibliothèques, vous allez bousiller.

est ici une version distillée de new opérateur de VS2005 new.cpp:

void * operator new(size_t size) _THROW1(_STD bad_alloc) 
{  // try to allocate size bytes 
    void *p; 
    while ((p = malloc(size)) == 0) 
    if (_callnewh(size) == 0) 
    {  // report no memory 
     static const std::bad_alloc nomem; 
     _RAISE(nomem); 
    } 

    return (p); 
} 
+3

En fait, j'avais une bonne raison de le faire une fois.Nous avons eu un "problème" de compilateur où il utilisait des tas de manière non sécurisée entre les limites de DLL. Le correctif consistait à créer une version personnalisée de "nouveau" qui utilisait un tas nommé spécifique. –

+0

Pourquoi n'avez-vous pas classé un bug et choisi plutôt de jouer avec le feu? – dirkgently

+0

Nous l'avons fait. La réponse que nous avons reçue était quelque chose du genre «les DLL ne fonctionnent pas très bien dans notre système». Nous avons fini par cesser de les utiliser, mais à court terme, cela a réglé le problème. –

4

Appelez-vous correctement l'opérateur surchargé, c'est-à-dire en lui passant les paramètres supplémentaires?

4

Le problème repose avec les deux arguments que vous avez ajoutés au nouvel opérateur surchargé. Essayez de rendre le nom de fichier et la ligne globale d'une certaine façon (ou les variables membres si vous surchargez new et supprimez pour une seule classe). Cela devrait mieux fonctionner.

12

Je pense que le problème ici est que le profil de votre nouveau profil ne correspond pas à celui de l'opérateur standard new, de sorte que l'on ne soit pas caché (et donc toujours utilisé).

vos profils de paramètres pour les nouveaux et supprimer besoin de ressembler à ceci:

void* operator new(size_t); 
void operator delete(void*, size_t); 
44

Peut-être que vous pouvez faire ce que vous voulez avec un peu de magie préprocesseur:

#include <iostream> 

using namespace std; 

void* operator new (size_t size, const char* filename, int line) { 
    void* ptr = new char[size]; 
    cout << "size = " << size << " filename = " << filename << " line = " << line << endl; 
    return ptr; 
} 

#define new new(__FILE__, __LINE__) 

int main() { 
    int* x = new int; 
} 
+12

C'est génial. –

+2

devrait-il être 'size_t' au lieu de' unsigned int'? Je crois que sur certaines plateformes, ces types ne sont pas équivalents. – iggy

+0

Pourquoi l'opérateur 'void * new (taille size_t, const char * nom de fichier, int line)' s le premier argument est 'size_t'? Si je veux remplacer l'opérateur 'delete', que dois-je écrire? – naive231

121

RE:

Ne jamais essayer de surcharger nouvelle/supprimer globalement

Pourquoi est-ce que lorsque quelqu'un tente d'utiliser une fonctionnalité moins courante de C++, quelqu'un agit comme si cela ne devait jamais être fait?

C'est fait tout le temps, c'est assez commun, et je n'ai pas travaillé pour une entreprise qui ne l'a pas fait.

Globalement surcharge et d'en supprimer sont extrêmement utiles dans la mémoire de suivi, des bugs de mémoire, les dépassements de mémoire tampon, etc.

Personne dans leur esprit va passer par un programme avec plusieurs millions de lignes de code, et ajouter un nouveau membre et supprimer à chaque classe. C'est juste stupide.

+1

Ce qui serait nécessaire ici est un * override * de new/delete plutôt que * overload *. J'ai dû le faire récemment (et la raison pour laquelle je suis tombé sur cette question) sur un système embarqué utilisant un RTOS. Bien que le RTOS fournisse des wrappers thread-safe pour malloc/free, l'application a été écrite en C++ avec new/delete. Pour forcer l'utilisation de malloc/delete, il était nécessaire de surcharger new/delete globalement. Cependant, les nouveaux [], supprimer [] et nouveau (std :: nothrow) et supprimer (std :: nothrow) doivent également être pris en compte. – Clifford

+0

La vérité est qu'il est beaucoup mieux d'abstraire le nouveau et supprimer avec une macro. NEW(), DELETE(). Cela vous permettra de faire des tâches supplémentaires comme tirer un cadre de pile, enregistrer un fichier et une ligne #, allouer à partir d'un tas prédéfini et le placer de nouveau en existence. La surcharge n'a tout simplement pas toute la flexibilité qui peut être obtenue grâce à une abstraction complète. – Dan

+1

En outre, l'écriture de votre propre système d'exploitation est une bonne application. – imallett

Questions connexes