2010-12-13 10 views
13

No tenía idea de por qué esto no funciona. El siguiente Function se crea mediante la colocación nueva. Se proporciona una función que verifica si se debe destruir, y si es así, llama a su destructor de forma manual.Destructor no llamado después de destruir la colocación de objetos -new'ed

Aquí es el caso de prueba en el que parece el destructor nunca es llamado:

/* Represents a function at runtime */ 
class Function { 
public: 
    /* Creates an invalid function */ 
    Function():codeptr(0) { } 

    /* Creates a function with the given code pointer */ 
    Function(void *codeptr):codeptr(codeptr) { } 

    /* Frees the function machine code */ 
    ~Function() { 
    if(*this) { 
     /* <- I explicitly put a debug output here! */ 
     destroyLLVMCode(codeptr); 
    } 
    } 

public: 
    /* Returns true if the function is valid 
    * (if the code pointer is non-null) 
    */ 
    operator bool() const { return codeptr != 0; } 

    /* Destroy this function by calling its destructor */ 
    void destroy() { ~Function(); } 

private: 
    void *codeptr; 
}; 

He utilizado este como la siguiente. Reduzca el código a continuación al mínimo que todavía muestra el problema. En mi programa real, por supuesto, la memoria se asigna de otra manera, desde un asignador.

#include <new> 
#include <cstdlib> 

int main() { 
    void *buffer = std::malloc(sizeof(Function)); 
    Function *f = new (buffer) Function(someExecutableLLVMCode); 
    /* more code .. register with symbol tables etc.. */ 
    f->destroy(); 
} 

Se puede ver que estoy llamando al destructor en la línea de lectura ~Function(). El compilador acepta, pero no termina llamándolo: lo verifiqué comprobando si realmente elimina el código LLVM que le di (ponga algún código en el destructor antes de eliminar el código LLVM al que apunta el codeptr, en caso de que Function es válido).

Me enteré después de lo que está causando eso. ¿Podría darme una explicación?

+0

Este código nunca crea una función de ninguna manera, y nunca llama a ningún método de función, por lo que no es sorprendente, tampoco destruye ningún objeto Function ... –

+0

@Johannes, ¿cómo se crea la instancia aquí? ¿Dónde está esa colocación 'nueva'? –

+0

@Johannes: toma un descanso, una siesta, lo que sea. ;-) su ejemplo de código no ilustra el problema. Estás diciendo que encontraste la causa pero estás pidiendo una explicación. esto es solo confuso ¿Puedes borrar la pregunta y publicarla mañana? –

Respuesta

24

Esto es porque ~Function(); no es una llamada de destructor sintácticamente aquí. Use this->~Function(); en su lugar.

~Function(); se analiza como un operador ~ y la creación del objeto Function en la pila. Function clase tiene un operator bool por eso se compilará esto.

+6

Pero si no es así, si tiene que escribir 'Function :: ~ Function()', digamos, ¿qué es '~ Function()' analizado como? ¿Aplica negación bit a bit a un objeto 'Function' temporal? Eso no debería compilar, creo. OH ACTUALIZACIÓN: tiene una conversión implícita a 'bool'. J O H A N N E S, ¡no hagas eso! –

+0

'Función :: ~ Función()' no funcionará tan bien. Standard dice que deberías escribir 'ptr-> ~ Function()'. –

+0

Bueno, la función :: ~ Function() funcionará bien. Pero tienes razón sobre '~ Function()'. Se describe en 5.3.1/9 en el sagrado estándar de C++. –

-1

Como recuerdo, el destructor no se puede llamar explícitamente. Intente mover el código de limpieza del destructor a otra función y llámelo en su lugar.

+0

Puede llamar a los destructores de forma explícita (es más difícil hablar explícitamente de las llamadas de los constructores ya que no hay sintaxis para las llamadas de los constructores, está en el nivel semántico, pero las llamadas al destructor ni siquiera tienen ese problema terminológico: todo está muy claro). –

+0

podemos llamar a un destructor explícitamente solo como a continuación :: Obj o; o. ~ Obj(); No me gusta cómo se hace en el método "mayBeDestroy". Debería haber dado un error de compilación. De lo contrario, debe llamarse como Función :: ~ Función(); – Arunmu

+0

Gracias, ya veo. – ruslik

8

Cambiar la llamada al destructor explícita a

this->~Function(); 

Actualmente la ~ función es la construcción de una "función" y luego llamar al operador ~ bit a bit, (legal porque tiene una conversión a bool), y luego destructing que , no el objeto llamado

Cuestiones relacionadas