// New.C - Implémentation du détecteur de fuites de mémoire #include #include #include #include "New.h" static void grow(int); // Pour allonger la taille du tableau Dse class Dse { // Une classe de stockage dynamique private: enum { delta = 256 }; // La taille de la liste de pointeurs void *pfs; // Pointeur vers le tas const char *fname; // Le nom du fichier pour un appel à new int lineno; // Le numéro de ligne pour un appel à new friend void grow(int); // Allonger le tableau Dse friend void *operator new(size_t, const char *, int); // allocation friend void operator delete(void *); // libération friend void mleak_check(); // Affichage des pointeurs alloués }; static Dse *plist = 0; // un pointeur de la liste static int plist_length = 0; // le nombre de pointeurs static int used = 0; // le nombre d'allocation void *operator new(size_t size, const char *file, int lineno) { void *pfs = malloc(size); // allocation de la mémoire if (pfs == 0) throw NewError(size, file, lineno); if (used == plist_length) // Temps pour grossir? grow(plist_length + Dse::delta); for (int i = 0; i < plist_length; i++) { if (plist[i].pfs == 0) { // available slot? plist[i].pfs = pfs; // sauvegarde du pointeur plist[i].fname = file; // sauvegarde du nom de fichier plist[i].lineno = lineno; // sauvegarde du numéro de la ligne used++; // incrémente le compteur return pfs; // retourne l'adresse mémoire } } throw NewError("internal error"); // Ne devrait jamais se produire } static void grow(int new_len) { // grossir le tableau Dse if (plist == 0) plist = static_cast(malloc(new_len * sizeof(Dse))); else plist = static_cast (realloc(plist, new_len * sizeof(Dse))); if (plist == 0) throw NewError("no heap memory"); for (int i = plist_length; i < new_len; i++) plist[i].pfs = 0; // initialise à 0 plist_length = new_len; // MàJ de la nouvelle taille } void operator delete(void *pfs) { if (pfs == 0) // faire que la commande "delete 0" soit sans effet return; for (int i = 0; i < plist_length; i++) if (plist[i].pfs == pfs) { // est-ce un pointeur? plist[i].pfs = 0; // le rendre disponible free(pfs); // libérer le pointeur used--; // décrementer le compteur return; } throw NewError(pfs); // adresse non disponible } void *operator new[](size_t size, const char *file, int lineno) { return operator new(size, file, lineno); } void operator delete[](void *pfs) { operator delete(pfs); } void mleak_check() { // afficher les pointeurs alloués if (used) // fuites de mémoire? for (int i = 0; i < plist_length; i++) if (plist[i].pfs) { // pointeurs restants? cerr << "Memory Leak:" << endl; cerr << "\tFilename: " << plist[i].fname << endl; cerr << "\tLine Number: " << plist[i].lineno << endl; cerr << "\tPointer address: " << plist[i].pfs << endl; } }