if (! this) {return false; } - PullRequest
       21

if (! this) {return false; }

10 голосов
/ 19 марта 2009

Я наткнулся на этот кусок кода, который кажется мне полностью сломанным, но бывает, что this равен null. Я просто не понимаю, как это может быть null

внутри обычного вызова метода, такого как

myObject->func();

внутри MyObject::func() у нас

if (!this) { return false; }

есть ли способ, которым я могу получить первую строку, чтобы бросить NullPointerException вместо того, чтобы идти внутри null (?) Метода?

Ответы [ 7 ]

22 голосов
/ 19 марта 2009

Если у вас есть:

MyObject *o = NULL;

o->func();

Что будет дальше, зависит от того, является ли func виртуальным. Если это так, то произойдет сбой, потому что ему нужен объект для получения vtable. Но если он не виртуальный, вызов продолжается с указателем this, установленным в NULL.

Я полагаю, что стандарт говорит, что это "неопределенное поведение", поэтому может произойти все что угодно, но типичные компиляторы просто генерируют код, чтобы не проверять, равен ли указатель NULL. Некоторые хорошо известные библиотеки полагаются на поведение, которое я описал: MFC имеет функцию с именем что-то вроде SafeGetHandle, которая может вызываться по нулевому указателю, и в этом случае возвращает NULL.

Возможно, вы захотите написать вспомогательную функцию многократного использования:

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

Затем вы можете использовать это в начале функции для проверки всех ее аргументов, включая this:

CheckNotNull(this);
2 голосов
/ 19 марта 2009

Способ отловить ошибки такого рода (по замыслу) - использовать класс-оболочку указателя (напоминающий shared_ptr), который генерируется при создании с аргументом нулевого указателя. Это может также произойти при разыменовании, но это немного поздно - я думаю, лучше, чем ничего.

1 голос
/ 19 марта 2009

(this == NULL) - неопределенное поведение в соответствии со стандартом. Я думаю, что вы должны удалить эту проверку:)

Предположим, мы делаем следующий вызов:

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

Поведение уже не определено, так зачем беспокоиться о проверке этого == NULL в CSomeClass :: method?

РЕДАКТИРОВАНИЕ: Я предполагаю, что ваш компилятор будет обрабатывать (0 == это), если вы не используете переменные-члены, но где он найдет указатель виртуальной таблицы? В этом случае ваш класс не может использовать полиморфизм.

1 голос
/ 19 марта 2009

Возможно, что this может быть нулевым. Я подозреваю, что этот код пытается (плохо) обнаружить состояние гонки, когда объект еще не завершен, инициализируется или был удален.

1 голос
/ 19 марта 2009
if(this == null)
   throw new NullPointerException;
if(!this)
   return false;
0 голосов
/ 19 марта 2009

этот указатель может стать нулевым в случаях, подобных этим:

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

Думаю, кто-то быстро взломал, чтобы избежать исключения нарушения прав доступа.

0 голосов
/ 19 марта 2009

this == null должно происходить только в том случае, если вы вызываете метод для удаленного объекта или если что-то записывает в память то, что не должно (и перезаписывает объектный указатель this в частности).

Вам следует выяснить, что на самом деле не так с вашим кодом, а не пытаться обходить его таким образом.

...