2009-02-24 6 views
19

Sto facendo un piccolo leak finder di memoria nel mio programma, ma il mio modo di sovraccaricare new e delete (e anche new [] e delete []) non sembra fare nulla.overloading new/delete

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

Il modo sovraccaricato new è mostrato nel frammento di codice di cui sopra. Immagino che sia qualcosa con l'operatore che ritorna vuoto * ma non so cosa fare al riguardo.

+6

"non sembra fare nulla": cosa intendi? Hai sovraccaricato l'operatore, ma non hai * sovrascritto * l'operatore predefinito nuovo, quindi "nuova x" chiama il nuovo predefinito mentre "nuovo (nome file, riga) x" chiama la tua versione sovraccaricata. –

risposta

11
void* ptr = new void[size]; 

Impossibile farlo. Aggiustalo.

Mai e poi mai provare a sovraccaricare nuovo/eliminare globalmente. O li hanno in una classe base e derivano tutti gli oggetti da questa classe o usano uno spazio dei nomi o un parametro di allocazione dei template. Perché, potresti chiedere. Perché nel caso in cui il tuo programma sia più di un singolo file e usi STL o altre librerie stai per rovinare.

Ecco una versione distillata di new operatore 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

In realtà, avevo una buona ragione per farlo una volta.Avevamo un "problema" del compilatore in cui utilizzava gli heap in modo non sicuro attraverso i limiti della DLL. La correzione era di creare una versione personalizzata di "nuovo" che utilizzava un heap specifico denominato. –

+0

Perché non hai inserito un bug e invece hai scelto di giocare con il fuoco? – dirkgently

+0

Abbiamo fatto. La risposta che abbiamo ottenuto era qualcosa del tipo "Le DLL non funzionano molto bene nel processo di cross-process nel nostro sistema". Alla fine abbiamo smesso di usarli, ma a breve termine questo ha risolto il problema. –

4

Si sta richiamando correttamente l'operatore sovraccarico, cioè passando i parametri aggiuntivi?

4

Il problema si affida con i due argomenti che sono stati aggiunti al nuovo operatore di overload. Prova a fare in modo che il nome file e la linea siano globali (o le variabili membro se stai sovraccaricando new e delete per una singola classe). Dovrebbe funzionare meglio.

12

Penso che il problema qui sia che il profilo dei parametri del nuovo utente non corrisponde a quello dell'operatore standard nuovo, in modo che uno non venga nascosto (e sia quindi ancora in uso).

i profili dei parametri per new e delete necessità di simile a questa:

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

Forse si può fare quello che vuoi con un po 'di magia preprocessore:

#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

Questo è fantastico. –

+2

dovrebbe essere 'size_t' invece di' unsigned int'? Credo che su alcune piattaforme questi tipi non siano equivalenti. – iggy

+0

Perché l'operatore void * new (dimensione size_t, const char * nomefile, riga int) 'Il primo argomento di' 'è' size_t'? Se voglio sovrascrivere l'operatore 'delete', cosa dovrei scrivere? – naive231

121

RE:

Mai e poi mai provare a sovraccaricare nuovo/eliminare globalmente

Perché quando qualcuno tenta di utilizzare una funzionalità meno comune di C++, qualcuno si comporta come non dovrebbe mai essere fatto?

È fatto tutto il tempo, è abbastanza comune, e non ho lavorato per società che non lo facevano.

Globalmente sovraccarico new e delete sono estremamente utile nel monitoraggio della memoria, i bug di memoria, buffer overrun, ecc

Nessuno sano di mente sta per passare attraverso un programma con diversi milioni di linee di codice, e aggiungere un nuovo ed elimina membro per ogni classe. È semplicemente stupido.

+1

Quello che sarebbe necessario qui è un * override * di new/delete piuttosto che * overload *. Ho dovuto farlo di recente (e il motivo per cui ho trovato questa domanda) su un sistema embedded usando un RTOS. Sebbene RTOS fornisca wrapper thread-safe per malloc/free, l'applicazione è stata scritta in C++ con new/delete. Per forzare l'uso del malloc/delete sicuro per i thread, era necessario eseguire l'override di new/delete a livello globale. Comunque anche i nuovi [], delete [] e new (std :: nothrow) e delete (std :: nothrow) devono essere considerati. – Clifford

+0

La verità è che è molto meglio astrarre il nuovo ed eliminare via con una macro. NUOVO(), ELIMINA(). Ciò ti consentirà di svolgere attività aggiuntive come tirare una cornice di stack, registrare un file e una linea #, allocare da un heap predefinito e posizionarlo nuovamente in esistenza. Il sovraccarico non ha la gamma completa di flessibilità che può essere raggiunta attraverso un'astrazione completa. – Dan

+1

Inoltre, scrivere il proprio sistema operativo è una buona applicazione. – imallett