2010-12-13 5 views
13

Non avevo idea del perché questo non funziona. Il seguente Function viene creato dal posizionamento nuovo. Viene fornita una funzione che controlla se deve essere distrutta e, in tal caso, chiama manualmente il suo distruttore.Il distruttore non ha chiamato dopo aver distrutto il posizionamento dell'oggetto-new'ed

Ecco il testcase in cui sembra il distruttore non viene mai chiamato:

/* 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; 
}; 

ho usato questo come il seguente. Taglia il codice sotto al minimo che presenta ancora il problema. Nel mio vero programma, ovviamente, la memoria è allocata in un altro modo, da un allocatore.

#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(); 
} 

Si può vedere che sto chiamando il distruttore nella linea di lettura ~Function(). Il compilatore accetta, ma non finisce per chiamarlo: l'ho verificato controllando se veramente cancella il codice LLVM che ho fornito (inserire del codice nel distruttore prima di cancellare il codice LLVM a cui punta il codeptr, nel caso Function è valido).

Ho scoperto in seguito cosa lo sta causando. Potresti fornirmi una spiegazione?

+0

Questo codice non crea mai una funzione in alcun modo e non chiama mai alcun metodo di funzione, quindi non sorprende non distrugge mai alcun oggetto funzione ... –

+0

@Johannes, come si crea l'istanza qui? Dov'è il posizionamento 'nuovo'? –

+0

@Johannes: fai una pausa, un pisolino, qualunque cosa. ;-) il tuo esempio di codice non illustra il problema. stai dicendo che hai trovato la causa ma stai chiedendo una spiegazione. questo è solo confuso. puoi cancellare la domanda e postare domani? –

risposta

24

Questo perché ~Function(); non è una chiamata distruttore sintatticamente qui. Utilizzare invece this->~Function();.

~Function(); viene analizzato come operatore ~ e creazione dell'oggetto Function nello stack. La classe Function ha un operator bool è per questo che verrà compilato.

+6

Ma se non lo è, se si deve scrivere 'Funzione :: ~ Funzione()', dire, allora cosa è '~ Funzione()' analizzato come? Applicando la negazione bit per bit a un oggetto 'Function' temporaneo? Questo non dovrebbe essere compilato, penso. OH UPDATE: ha una conversione implicita a 'bool'. J O H A N N E S, non farlo! –

+0

'Funzione :: ~ Funzione()' non funzionerà bene. Lo standard dice che dovresti scrivere 'ptr-> ~ Function()'. –

+0

Bene, la funzione :: ~ Function() funzionerà correttamente. Ma hai ragione su '~ Function()'. È descritto in 5.3.1/9 nel sacro standard C++. –

-1

Come ricordo il distruttore non può essere chiamato in modo esplicito. Prova a spostare il codice di pulizia dal distruttore su un'altra funzione e chiamalo invece.

+0

Puoi chiamare i distruttori in modo esplicito (è più difficile discutere le chiamate di costruttori espliciti poiché non c'è alcuna sintassi per le chiamate del costruttore, è a livello semantico, ma chiamate del distruttore non ho nemmeno quel problema terminologico: è tutto molto chiaro). –

+0

possiamo chiamare un distruttore esplicitamente solo come sotto :: Obj o; o. ~ Obj(); Non come nel metodo "mayBeDestroy". Dovrebbe aver dato un errore di compilazione. Altrimenti deve essere chiamato come Funzione :: ~ Funzione(); – Arunmu

+0

Grazie, ora vedo. – ruslik

8

Cambia la chiamata distruttore esplicito al

this->~Function(); 

Attualmente il ~ Funzione sta costruendo una "funzione" e quindi chiamando il ~ operatore bit a bit, (legale perché si ha una conversione a bool), e poi destructing che , non l'oggetto chiamato.

Problemi correlati