2010-12-13 33 views
13

Je n'avais aucune idée pourquoi cela ne fonctionne pas. Le Function suivant est créé par placement nouveau. Une fonction est fournie qui vérifie si elle doit être détruite, et si c'est le cas, appelle son destructeur manuellement.Destructeur non appelé après la destruction de l'objet-new'ed

est ici le cas de test où il semble que le destructor est jamais appelé:

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

je cela comme suit. Réduisez le code ci-dessous au minimum qui présente toujours le problème. Dans mon vrai programme, bien sûr, la mémoire est allouée d'une autre manière, à partir d'un allocateur.

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

Vous pouvez voir que je vais appeler la destructor dans la ligne de lecture ~Function(). Le compilateur accepte, mais il ne finit pas par l'appeler: je l'ai vérifié en vérifiant s'il supprime vraiment le code LLVM que je lui ai donné (mettez du code dans le destructeur avant de supprimer le code LLVM que le codeptr pointe vers, dans le cas Function est valide).

J'ai découvert plus tard ce qui cause cela. Pourriez-vous s'il vous plaît me fournir une explication?

+0

Ce code ne crée jamais une fonction de quelque façon que ce soit, et n'appelle jamais aucune méthode de Fonction, donc il ne surprend pas et ne détruit jamais aucun objet Fonction ... –

+0

@Johannes, comment créer l'instance ici? Où est ce placement 'nouveau'? –

+0

@Johannes: faire une pause, une sieste, peu importe. ;-) votre exemple de code n'illustre pas le problème. vous dites que vous avez trouvé la cause, mais vous demandez une explication. C'est juste embrouillé. pouvez-vous supprimer la question et poster demain? –

Répondre

24

Ceci est dû au fait que ~Function(); n'est pas un appel de destructeur syntaxiquement ici. Utilisez this->~Function(); à la place.

~Function(); est analysé en tant qu'opérateur ~ et création de l'objet Function sur la pile. La classe Function a un operator bool c'est pourquoi cela sera compilé.

+6

Mais si ce n'est pas le cas, si vous devez écrire 'Function :: ~ Function()', dites, alors qu'est-ce que '~ Function()' interprété comme? Appliquer une négation bit à un objet 'Function' temporaire? Cela ne devrait pas compiler, je pense. OH UPDATE: il a une conversion implicite en 'bool'. J O H A N N E S, ne fais pas ça! –

+0

'Function :: ~ Function()' ne fonctionnera pas aussi bien. Standard dit que vous devriez écrire 'ptr-> ~ Function()'. –

+0

Eh bien, Function :: ~ Function() fonctionnera bien. Mais vous avez raison à propos de '~ Function()'. Il est décrit en 5.3.1/9 dans la norme C++. –

-1

Si je me souviens bien, le destructeur ne peut pas être appelé explicitement. Essayez de déplacer le code de nettoyage du destructeur vers une autre fonction et appelez-le à la place.

+0

Vous pouvez appeler des destructeurs explicitement (il est plus difficile de discuter des appels constructeurs explicites car il n'y a aucune syntaxe pour les appels constructeurs, c'est au niveau sémantique, mais les appels destructeurs n'a même pas ce problème terminologique: tout est très clair). –

+0

nous pouvons appeler un destructeur expictivement seulement comme ci-dessous :: Obj o; o. ~ Obj(); Pas comme comment c'est fait dans la méthode "mayBeDestroy". Il aurait dû donner une erreur de compilation. Sinon, il doit être appelé en tant que Function :: ~ Function(); – Arunmu

+0

Merci, je vois maintenant. – ruslik

8

Changer votre appel explicite destructor à

this->~Function(); 

Actuellement, la fonction ~ construit une « fonction », puis d'appeler l'opérateur ~ bitwise, (juridique parce que vous avez une conversion à Bool) et autodestructrices alors que , pas l'objet appelé.