2010-10-31 9 views
23

Estoy trabajando en la modificación de un programa C++ relativamente grande, donde desafortunadamente no siempre está claro si alguien antes que yo usó sintaxis C o C++ (esto es en el departamento de ingeniería eléctrica en una universidad, y EEs siempre estamos tentados de usar C para todo, y lamentablemente en este caso, la gente puede salirse con la suya).objeto C++ creado con nuevo, destruido con free(); ¿Qué tan malo es esto?

Sin embargo, si alguien crea un objeto:

Packet* thePacket = new Packet();

qué es importante que se está destruida con delete thePacket; o free(thePacket);?

Me doy cuenta de que eliminar llama al destructor mientras que free() no lo hace, pero Packet no tiene un destructor. Estoy teniendo un terrible momento atrapado en un pantano de gestión de la memoria aquí y estoy pensando que este puede ser uno de los muchos problemas.

+4

El paquete tiene un destructor, incluso si no puede verlo. Es ... gah, responde abajo. – slezica

+0

La respuesta correcta es que no debería estar borrando cosas. Abrázalos. – GManNickG

Respuesta

33

Sí, sí importa.

Para la memoria obtenida usando new usted debe use delete.

Para la memoria obtenida usando malloc usted debe use free.

new y malloc pueden usar estructuras de datos diferentes internamente para realizar un seguimiento de qué y dónde ha asignado la memoria. Entonces, para liberar memoria, debe llamar a la función correspondiente que conoce esas estructuras de datos. Sin embargo, en general es una mala idea mezclar estos dos tipos de asignación de memoria en una pieza de código.

+4

'new' y' malloc' ** pueden ** usar diferentes estructuras de datos internamente para realizar un seguimiento de las asignaciones de memoria. Ellos no tienen que hacerlo. –

+1

Gracias! Solo el tipo de respuesta que estaba buscando. Yaay por revisar el código de otras personas para ver qué usaron para crear qué ... va a ser divertido. Dmitri

+0

@Dmitri Te escucho :) y eres bienvenido. Hora para el poderoso grep – srean

19

Si llama al free(), no se llama al destructor.

Además, hay no guarantee that new and free operate on the same heap.

También puede anular new y delete especialmente para operar en una clase en particular. Si lo hace, pero llame al free() en lugar del delete personalizado, entonces omite cualquier comportamiento especial que haya escrito en delete. (Pero probablemente no harías esta pregunta si hubieras hecho eso, porque sabrías qué comportamientos te faltaban ...)

+0

Gracias. Ver mi comentario en Omnifarious 'post (estaba leyendo de abajo hacia arriba) – Dmitri

+0

@Dmitri, no estaba sugiriendo redefinir 'delete' como solución - estaba señalando como otro posible problema. He editado mi respuesta para aclarar un poco más. –

+0

Si anula el 'nuevo' y' eliminar' global, entonces * tiene * para usar 'malloc()' y 'libre()'. – wilhelmtell

4

Tienes toda la razón, es NO correcto. Como dijiste a ti mismo, libre no llamarás al destructor. Incluso si Packet no tiene un destructor explícito, está usando uno heredado.

El uso de free en un objeto creado con new es como destruir solo lo que una copia superficial alcanzaría. Destrucción profunda NECESITA la función de destructor.

Además, no estoy seguro de que los objetos creados con new() estén en el mismo mapa de memoria que la memoria malloc() 'd. No están garantizados, creo.

5

tiene un destructor, incluso si no lo ha declarado explícitamente. Tiene un destructor predeterminado. El destructor predeterminado probablemente no hace mucho, pero no puede contar con que ese sea el caso. Depende del compilador lo que hace.

new y malloc también pueden tener implementaciones muy diferentes. Por ejemplo, siempre se llama a eliminar en un contexto donde tiene información perfecta sobre el tamaño de la estructura de datos que está eliminando en tiempo de compilación. free no tiene este lujo. Es posible que el asignador que está usando new no almacene los bytes al principio del área de memoria indicando cuántos bytes ocupa. Esto llevaría a free a hacer algo completamente incorrecto y bloquear su programa al liberar algo asignado con new.

Personalmente, si hacer que la gente a hacer lo correcto, o fijar el código de sí mismo es completamente imposible, yo anunciare mi propio mundial operator new que llama malloc por lo que entonces free sin duda no accidente, aunque todavía no lo llamaría el destructor en general ser realmente feo.

4

En resumen, es tan malo como el comportamiento indefinido.

Esto es silencioso que se explica por sí mismo.

C estándar ($ 7.20.3.2/2) - "El función libre hace que el espacio se refirió a por ptr a cancelar la asignación, es decir, entrega para su posterior asignación Si ptr es un puntero nulo. , ninguna acción ocurre. de lo contrario, si el argumento qué no coincide con un puntero antes devuelta por la calloc, malloc, o función realloc, o si el espacio se ha sido desasignado por una llamada a liberar o realloc, el comportamiento es indefinido."

1

si alguien crea un objeto:

Packet* thePacket = new Packet(); 

qué es importante que se destruye con thePacket borrado; o gratis (el Paquete); ?

Sí, importa. free (thePacket) invocaría Comportamiento no definido pero delete thePacket no lo haría y todos sabemos que el Comportamiento no definido puede tener consecuencias desastrosas.

Cuestiones relacionadas