Question

Je suis tombé par hasard sur ce code qui semble totalement brisé pour moi, mais il se trouve que this est null. Je ne comprends pas comment cela peut être MyObject::func()

il se trouve dans un appel de méthode normal tel que

myObject->func();

à l'intérieur NullPointerException nous avons

if (!this) { return false; }

Existe-t-il un moyen quelconque pour que la première ligne jette un <=> au lieu d'entrer dans la méthode <=> (?)?

Était-ce utile?

La solution

Si vous avez:

MyObject *o = NULL;

o->func();

Ce qui se passe ensuite dépend de si func est virtuel. Si c'est le cas, alors il va planter, car il a besoin d'un objet pour obtenir la vtable. Mais si ce n’est pas virtuel, l’appel se poursuit avec le pointeur this défini sur NULL.

Je pense que la norme indique qu'il s'agit de & "comportement non défini &"; tout peut donc arriver, mais les compilateurs classiques génèrent simplement le code pour ne pas vérifier si le pointeur est NULL. Certaines bibliothèques bien connues reposent sur le comportement que j'ai décrit: MFC a une fonction appelée quelque chose comme SafeGetHandle qui peut être appelée sur un pointeur null et renvoie NULL dans ce cas.

Vous pouvez écrire une fonction d'assistance réutilisable:

void CheckNotNull(void *p)
{
    if (p == NULL)
        throw NullPointerException();
}

Vous pouvez ensuite l'utiliser au début d'une fonction pour vérifier tous ses arguments, y compris this:

CheckNotNull(this);

Autres conseils

Un moyen de piéger ce type d’erreurs (de par leur conception) consiste à utiliser une classe de wrapper de pointeur (ressemblant à un shared_ptr) qui est générée lors de la création avec un argument de pointeur nul. Il peut aussi lancer quand on en déréférence, mais c'est un peu tard - mieux que rien, je suppose.

if(this == null)
   throw new NullPointerException;
if(!this)
   return false;

(this == NULL) est un comportement indéfini selon la norme. Je pense que vous devriez enlever cette vérification:)

Supposons que nous passions l'appel suivant:

((CSomeClass*) 0)->method();

Le comportement est déjà indéfini, alors pourquoi se donner la peine de vérifier ceci == NULL dans CSomeClass :: method?

MODIFIÉ: Je suppose que votre compilateur gérera (0 == ceci) si vous n'utilisez pas de variables membres, mais où trouverait-il le pointeur de la table virtuelle? Dans ce cas, votre classe ne peut pas utiliser le polymoprhisme.

Il est possible que this soit nul. Je soupçonne que ce code tente de détecter (mal) une condition de concurrence critique dans laquelle l'objet n'a pas encore été initialisé ou a été supprimé.

ce pointeur peut devenir nul dans les cas suivants:

class Test
{

public:
    bool f();

private:
    int m_i;
};


bool Test::f()
{
    if(!this)
    {
        return false;
    }

    m_i = 0;
    return true;

}


int main(int argc, char **argv)
{
    Test* p = new Test;
    delete p;
    p = NULL;

    p->f();
}

Je suppose que quelqu'un a fait un petit coup rapide pour éviter l'exception relative aux violations d'accès.

this == null ne devrait se produire que si vous appelez une méthode sur un objet supprimé ou si quelque chose est en train d'écrire en mémoire et qu'elle ne devrait pas (et écrasant en particulier le pointeur this de cet objet).

Vous devriez rechercher ce qui ne va vraiment pas avec votre code plutôt que d'essayer de le contourner comme ceci.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top