2009-09-08 15 views
5

Estoy tratando de escribir un perfilador de memoria y hasta ahora he podido hacer que mis funciones personalizadas funcionen para malloc, gratis, nuevo y eliminar. Traté de usar __FILE__ y __LINE__ para registrar el originador dentro del nuevo método sobrecargado, pero (como se esperaba) simplemente proporciona los detalles de dónde está la función sobrecargada. ¿Hay alguna manera de obtener los detalles sobre el originador de las funciones sobrecargadas sin realizar ningún cambio en el código existente del componente que se está probando (como #define para malloc)?Reemplazando "nuevo" y registrando datos sobre la persona que llama

La función que estoy usando es:

void* operator new (size_t size) 
{ 
    if(b_MemProfStarted) 
    { 
     b_MemProfStarted = false; 
     o_MemLogFile << "NEW: " << "| Caller: "<< __FILE__ << ":" 
       << __LINE__ << endl; 
     b_MemProfStarted = true; 
    } 

    void *p=malloc(size); 
    if (p==0) // did malloc succeed? 
    throw std::bad_alloc(); // ANSI/ISO compliant behavior 

    return p; 
} 

El bool b_MemProfStarted se utiliza para evitar las llamadas recursivas en ofstream y map.insert.

Respuesta

3

Puede escribir

new(foo, bar) MyClass; 

En este caso, la siguiente función se llama

void*operator new(std::size_t, Foo, Bar){ 
    ... 
} 

Ahora puede llamar

new(__LINE__, __FILE__) MyClass; 

y utilizar los datos con

void*operator new(std::size_t, unsigned line, const char*file){ 
    ... 
} 

Adición de una macro

#define new new(__LINE__, __FILE__) 

al código que está siendo monitorizado detectará la mayoría de invocaciones sin necesidad de cambios en el código fuente.

No es perfecto ya que podría llamar al operador nuevo directamente, por ejemplo. En ese caso, el preprocesador convertirá su código en basura. Sin embargo, no conozco una mejor manera.

+0

Como 'new' es una palabra clave, intentar volver a definir con un macro es un comportamiento indefinido (excepciones específicas del compilador exceptuadas). Prefiero definir condicionalmente una macro DEBUG_NEW_PLACEMENT para 'new's 'normales' y dejar explícito' operator new' y special placement 'new's solo. Sin embargo, todavía no es una solución bonita. –

+0

void * operator new (std :: size_t, línea sin firmar, const char * file) fallaría porque "nuevo" solo toma size_t. No se puede usar "#define new new (__ LINE__, __FILE__)" y el operador anula el uno al otro juntos, ya que intentaría reemplazar el "nuevo" en la definición de la función de anulación. void * operator new (std :: size_t) -> void * operator new (__ LINE__, __FILE __)/* recursive? */(Std :: size_t) – Gayan

+0

@Charles Bailey - ¿Podrías dar más detalles? No estoy familiarizado con DEBUG_NEW_PLACEMENT Intenté "#define new (size) My_New (size, __FILE__, __LINE__)" pero parece que no se llama cuando se hace una "nueva" – Gayan

Cuestiones relacionadas