2011-11-18 12 views
47

Prima di tutto, c'erano almeno 4-5 argomenti con un argomento simile su SO. Leggo ciascuno di loro e non credo che mi aiutino davvero con questo specifico problema. Se qualcun altro trova una domanda duplicata, mi scuso. Ho fatto la mia parte di ricerche prima di pubblicare questo, poiché sembra una domanda molto comune.Come sostituire correttamente gli operatori globali nuovi e di eliminazione

sto usando Visual Studio .NET 2003 su Windows 7.

ho i miei sovraccarichi di nuovo eliminare quel punto/alla mia personalizzato chiamate a malloc() e free() per la diagnostica. I miei nuovi overload/delete sono in un file di intestazione che ho incluso in alcuni file.

Il problema è che la base di codice è praticamente spaghetti e non esiste un modo semplice per assicurarsi che questi sovraccarichi vengano utilizzati da tutto. Sono incluse le librerie di terze parti che sono black-box. Usiamo anche STL ovunque.

Nei miei test ho riscontrato che STL sta ancora missando le chiamate al mio nuovo/delete e alle nuove chiamate MSVC standard/di eliminazione.

Non sembra realistico includere il mio file di intestazione in migliaia di altri file, che richiederebbero troppo tempo. Qualcuno può offrire alcuni suggerimenti su come correttamente ed efficacemente sovraccaricare nuovo/eliminare globalmente, quindi tutto utilizza il mio gestore di memoria personalizzato?

+0

Se si definiscono gli operatori a livello mondiale in un colpo di testa pre-compilato che dovrebbero coprire il più a terra. In alternativa è possibile utilizzare le funzioni di heap CRT se questo è per rilevare perdite di memoria. – AJG85

risposta

63

Non è così che funziona. È sostituire i due operatori, e questo è fatto al tempo link. Tutto quello che devi fare è scrivere una TU singola che definisce questi operatori e collegarla al mix. Nessun altro mai ha bisogno di sapere su questo:

// optional_ops.cpp 

void * operator new(std::size_t n) throw(std::bad_alloc) 
{ 
    //... 
} 
void operator delete(void * p) throw() 
{ 
    //... 
} 

In linea di principio, non c'è bisogno di alcun file di intestazione per dichiarare queste funzioni (operator new, operator delete), dal momento che i dichiarazioni di queste due funzioni sono già insita nel lingua, se vuoi Tuttavia, i nomi std, std::bad_alloc e std::size_t sono non predeclared, quindi probabilmente vorrai includere <new> o qualche altra intestazione per fornire quei nomi.

In C++ 11 e oltre, è possibile utilizzare alternativamente decltype(sizeof(0)) per ottenere la dimensione del primo parametro in un modo che non richiede alcun tipo di libreria. C++ 11 ha anche un modello di eccezione più semplice senza specifiche di eccezione dinamiche (che sono state finalmente rimosse dal linguaggio interamente in C++ 17).

void * operator new(decltype(sizeof(0)) n) noexcept(false) 
{ 
    //... 
} 
+1

Il linker non si lamenterà delle definizioni duplicate? Penso che l'ODR si applica qui. Per non dire che abbiamo 120 DLL che costruiamo e dovrei collegarlo in ognuno di quei progetti DLL. Immagino che sia ancora meglio delle alternative. –

+3

@RobertDailey: No, caso speciale, coperto dallo standard, riferimenti deboli, ecc. In realtà ho segnalato un bug in GCC riguardo questo l'altro giorno, quindi con l'ultima versione questo dovrebbe funzionare anche con '-fwhole-program' e '-flto' e whatnot (vedi [qui] (http://stackoverflow.com/questions/7629270/how-does-stdstring-allocate-memory-in-gcc-with-fwhole-program) e [qui] (http :? //gcc.gnu.org/bugzilla/show_bug.cgi id = 50594).) ' –

+0

Puoi spiegare cosa intendi per" coperto dallo standard "e" riferimenti deboli "? Grazie!! –

31

aggiungere anche queste linee:

void *operator new[](std::size_t s) throw(std::bad_alloc) 
{ 
    // TODO: implement 
    return NULL; 
} 
void operator delete[](void *p) throw() 
{ 
    // TODO: implement 
} 
Problemi correlati