2010-11-27 11 views
5

Tengo el operador nuevo funcionando pero tan pronto como llamo eliminar, se bloquea en la línea free (ptr). ¿Alguien puede decir lo que estoy haciendo mal al sobrecargar operador nuevo y eliminar en esta clase Base? Sugerencia: no estoy preguntando sobre problemas de diseño.Operador eliminar causando daños en el montón mientras el operador funciona bien

class Base { 
private: 
    int i; 

public: 
    Base() : i (10) { 
    } 

    static void * operator new (size_t size) { 
     if (size = 0) size = 1; // please read this line carefully! size = 0! 
     return malloc (size); 
    } 

    static void operator delete (void *ptr, size_t size) { 
     if (ptr == NULL) return; 
     free (ptr); 
    } 
}; 
+1

¿Estás tratando de eliminar un objeto dos veces o eliminar un objeto a través de un puntero no obtenida de llamar 'new'? –

+0

Como nota al margen, 'free (NULL)' está garantizado para ser seguro (un no-op), por lo que no tiene que ser un caso especial. –

+0

hm ... Es malo: si reemplaza 'if (size == 0)' con 'if (size = 0)' y agrega un miembro de datos privados además de un constructor, el código fallará. Sé que 'size = 0' es un error que no debería ocurrir, pero el código falla ÚNICAMENTE cuando inicializas un miembro de datos privados de esta clase en el constructor. – Jaywalker

Respuesta

4

Esto funciona para mí:

#include <cstdlib> 
using namespace std; 
class Base { 
public: 
    void * operator new(size_t size) { 
     if (size == 0) size = 1; 
     return malloc (size); 
    } 

    void operator delete (void *ptr, size_t size) { 
     if (ptr == NULL) return; 
     free (ptr); 
    } 
}; 

int main() 
{ 
    Base* b = new Base; 
    delete b; 
    return 0; 
} 

[email protected]:/tmp$ g++ -o test test.cpp 
[email protected]:/tmp$ ./test 
[email protected]:/tmp$ valgrind ./test 
==7229== HEAP SUMMARY: 
==7229==  in use at exit: 0 bytes in 0 blocks 
==7229== total heap usage: 1 allocs, 1 frees, 1 bytes allocated 
==7229== 
==7229== All heap blocks were freed -- no leaks are possible 
==7229== 
==7229== For counts of detected and suppressed errors, rerun with: -v 
==7229== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) 
+0

Gracias. Sí, tu código está bien. He hecho algunos cambios adicionales en mi código. ¿Puedes comentar sobre eso? – Jaywalker

1

no veo ningún problema con el código de ejemplo que ha dado.

Lo siguiente funciona bien para mí.

[email protected] ~ $ cat leak_check.cpp && g++ leak_check.cpp && valgrind --leak-check=full ./a.out 
#include <cstdlib> 
class Base { 
public: 
    static void * operator new (size_t size) { 
     if (size == 0) size = 1; 
     return malloc (size); 
    } 

    static void operator delete (void *ptr, size_t size) { 
     if (ptr == NULL) return; 
     free (ptr); 
    } 
}; 

int main() 
{ 
    Base * p = (Base *) Base::operator new(sizeof(Base)); 
    Base::operator delete((void*)p,sizeof(Base)); 
} 
==4561== Memcheck, a memory error detector 
==4561== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==4561== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info 
==4561== Command: ./a.out 
==4561== 
==4561== 
==4561== HEAP SUMMARY: 
==4561==  in use at exit: 0 bytes in 0 blocks 
==4561== total heap usage: 1 allocs, 1 frees, 1 bytes allocated 
==4561== 
==4561== All heap blocks were freed -- no leaks are possible 
==4561== 
==4561== For counts of detected and suppressed errors, rerun with: -v 
==4561== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 6) 

Por cierto liberar un puntero nulo está perfectamente bien.

La función free hace que el espacio apuntado por ptr para cancelar la asignación, es decir, disponible para su posterior asignación. Si ptr es un puntero nulo, no se produce ninguna acción.

So if (ptr == NULL) return; se puede omitir.

2

El problema real no está en los operadores new ni delete. Su implementación de ellos es bastante sencilla, no hay problema aquí.

El problema real que tiene como corrupción de montón. Es causado por su código, no necesariamente el código que manipula los objetos Base. Es solo el montón de corrupción que se descubre exactamente cuando delete su objeto.

Probablemente tiene un código que hace daño al montón justo antes de delete su objeto.

Debe verificar el código de acceso a la memoria no válida. Esto incluye:

  1. Asegurar el cliente no accede más memoria que asigna
  2. asegurarse de que no utiliza la memoria después de liberar la misma.
  3. etc.
Cuestiones relacionadas