2009-02-24 9 views
19

Estoy haciendo un pequeño buscador de pérdida de memoria en mi programa, pero mi forma de sobrecargar nueva y eliminar (y también nueva [] y eliminar []) parece que no hace nada.sobrecarga nueva/eliminar

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 forma I sobrecargado new se muestra en el fragmento de código de seguridad. Supongo que es algo con el operador volviendo vacío * pero no sé qué hacer al respecto.

+6

"no parece hacer nada": ¿qué quieres decir? Sobrecargó el operador, pero no ha * reemplazado * el operador predeterminado nuevo, por lo que "nueva x" llama a la nueva predeterminada mientras que "nuevo (nombre de archivo, línea) x" llama a su versión sobrecargada. –

Respuesta

11
void* ptr = new void[size]; 

No se puede hacer eso. Arreglalo.

Nunca intente sobrecargar nueva/eliminar globalmente. O tenerlos en una clase base y derivar todos los objetos de esta clase o usar un espacio de nombres o un parámetro de asignación de plantilla. Por qué, puedes preguntar Porque en caso de que su programa sea más de un solo archivo y use STL u otras bibliotecas, se equivocará.

Aquí hay una versión destilada de new operador 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 realidad, tuve una buena razón para hacerlo una vez.Tuvimos un "problema" de compilación en el que se usaba montones de una manera insegura a través de límites DLL. La solución era crear una versión personalizada de "nuevo" que utilizara un montón con nombre específico. –

+0

¿Por qué no archivó un error y en su lugar eligió jugar con fuego? – dirkgently

+0

Lo hicimos. La respuesta que obtuvimos fue algo así como "Las DLL no funcionan muy bien en el proceso cruzado de nuestro sistema". Finalmente dejamos de usarlos, pero a corto plazo esto solucionó el problema. –

4

¿Está invocando correctamente el operador sobrecargado, es decir, pasándole los parámetros adicionales?

4

El problema se basa en los dos argumentos que se han añadido al nuevo operador sobrecargado. Intente hacer que el nombre del archivo y la línea sean globales de alguna manera (o variables miembro si está sobrecargando una nueva clase y eliminándola para una sola clase). Eso debería funcionar mejor.

12

Creo que el problema aquí es que el nuevo perfil de parámetros no coincide con el del operador estándar nuevo, por lo que uno no se oculta (y por lo tanto todavía se está utilizando).

Sus perfiles de los parámetros de nuevo y eliminar la necesidad de tener este aspecto:

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

Tal vez usted puede hacer lo que quiera con un poco de magia preprocesador:

#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

Esto es asombroso. –

+2

¿debería ser 'size_t' en lugar de' unsigned int'? Creo que en algunas plataformas estos tipos no son equivalentes. – iggy

+0

¿Por qué 'void * operator new (size_t size, const char * filename, int line)' El primer argumento es 'size_t'? Si quiero anular el operador 'borrar', ¿qué debo escribir? – naive231

121

RE:

Nunca jamás tratar de sobrecargar nueva/eliminar globalmente

¿Por qué cuando alguien intenta utilizar una función menos común de C++, alguien actúa como si nunca se hiciera?

Está hecho todo el tiempo, es bastante común, y no he trabajado para una empresa que no hizo esto.

A nivel mundial sobrecargado nuevo y borrar son extremadamente útiles en el seguimiento de la memoria, errores de memoria, desbordamientos de búfer, etc.

Nadie en su sano juicio va a ir a través de un programa con varios millones de líneas de código, y añadir una nuevo y eliminar miembro a todas y cada una de las clases. Eso es solo estúpido.

+1

Lo que se necesitaría aquí es una * anulación * de nueva/eliminar en lugar de * sobrecarga *. He tenido que hacer esto recientemente (y la razón por la que me encontré con esta pregunta) en un sistema integrado que usa un RTOS. Aunque el RTOS proporcionó envolturas thread-safe para malloc/free, la aplicación se escribió en C++ con new/delete. Para forzar el uso del malloc/delete seguro para subprocesos, era necesario anular el nuevo/eliminar globalmente. Sin embargo, los nuevos [], delete [] y new (std :: nothrow) y delete (std :: nothrow) también deben ser considerados. – Clifford

+0

La verdad es que es mucho mejor abstraer lo nuevo y eliminarlo con una macro. NUEVO(), ELIMINAR(). Esto le permitirá realizar tareas adicionales, como extraer un marco de pila, Registrar un archivo y un número de línea, Asignar desde un montón predefinido y colocarlo nuevo en existencia. La sobrecarga simplemente no tiene toda la gama de flexibilidad que se puede lograr a través de una abstracción completa. – Dan

+1

Además, escribir su propio sistema operativo es una buena aplicación. – imallett