Использование проверки указателя Assert и NULL, что лучше использовать

При программировании я использую assert, а также проверку указателя NULL.

Но насколько я знаю, assert будет полезен только в режиме DEBUG.

Мой вопрос заключается в том, что у меня есть внутренний указатель, который, я уверен, не может быть функцией примера NULL, возвращающей указатель (но указатель не является членом класса), в таких случаях я могу использовать assert

test* ptr = fun(); // return a pointer of type test
assert(ptr);

//do some operation

или проверка указателя NULL

test* ptr = fun(); // return a pointer of type test
assert(ptr);
if (NULL != ptr)
{
    //do some operation
}

Вот какая практика кода хороша. Насколько я понимаю, это будет вторая. Потому что я столкнулся с некоторыми ситуациями, когда значение ptr возвращает NULL из-за некоторых ненормальных случаев, о которых мы даже не можем подумать.

Но есть ли у нас другие лучшие варианты?


person Astro - Amit    schedule 11.01.2013    source источник
comment
Почему этот вопрос проголосовали за закрытие? Это правильный вопрос.   -  person Nawaz    schedule 11.01.2013
comment
Вы решили не возвращать null? Было бы намного проще написать код. т.е. пустые массивы/специальные нулевые объекты и исключения могут значительно ограничить необходимость возврата нулевого значения и, следовательно, его проверки. .   -  person Alexei Levenkov    schedule 11.01.2013
comment
@AlexeiLevenkov проверь второй случай   -  person Astro - Amit    schedule 11.01.2013
comment
Который из? Вы показываете только один случай, когда функция возвращает значение null, и вы сказали, что эта функция имеет контракт, который никогда не возвращает значение null, но не соблюдает его. Сбой с отказом в доступе в этом случае может быть только хуже, чем сбой с пользовательским исключением в этом случае...   -  person Alexei Levenkov    schedule 11.01.2013
comment
Если вы влюблены в assert(), делайте оба в согласии. assert(ptr && "Unexpected NULL pointer"); if (ptr) {...}. Выбор only assert() игнорирует причину, по которой вы утверждаете в первую очередь в релизных сборках, и выбираете только if (ptr) скрывает неожиданное, с которым вы педантично начинаете в сборках отладки.   -  person WhozCraig    schedule 11.01.2013
comment
@WhozCraig, можете ли вы сказать мне, почему мы должны давать чек на if (ptr) ptr не является логическим значением. Поэтому я думаю, что лучше использовать как ** if ( NULL != ptr) **   -  person Astro - Amit    schedule 11.01.2013
comment
@ Amit0440 в C и C++ ноль подразумевает false, ненулевое значение подразумевает true для целей логической оценки. Честно говоря, это вопрос вкуса на данный момент в языках C и C++ уже многих поколений. Каждому свое.   -  person WhozCraig    schedule 11.01.2013


Ответы (5)


Реальное решение зависит от семантики функции fun.

Если возврат NULL семантически недействителен, то я думаю, что fun должен вызывать соответствующее исключение (например, std::logic_error1) вместо возврата NULL, и вы можете использовать assert на сайте вызова, чтобы убедиться, что fun работает нормально. , и если он не работает нормально, прервите программу. Таким образом, ошибка в fun не распространяется на остальную часть программы, так как она сразу же обнаруживается.

Однако, если возврат NULL из fun семантически корректен, то вам следует проверить возвращаемое значение на сайте вызова с помощью if, а assert в этом случае на самом деле не требуется, потому что вы все равно будете использовать if.

1. Или вы можете использовать std::runtime_error или std::domain_error.

person Nawaz    schedule 11.01.2013
comment
некоторые ненормальные сценарии могут привести к тому, что значение будет возвращено fun как NULL или повреждение памяти для этой переменной. Так же и некоторые другие потоки. Что, наконец, означает, что я вынужден использовать второй случай... - person Astro - Amit; 11.01.2013

assert говорит: «Если это не так, в моем коде есть логическая ошибка». Если вы добавляете код для обработки того факта, что указатель может быть нулевым, то вызов assert является избыточным. Вместо этого вы должны добавить ведение журнала и обработку в случай «иначе». Таким образом, ваша сборка отладки будет работать так же, как и сборка выпуска, даже в случае нулевого указателя.

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

Единственная причина для утверждения только для отладки — это проверка логической ошибки, которую слишком дорого делать в коде выпуска. Обычно нулевая проверка указателя не попадает в эту категорию.

person CB Bailey    schedule 11.01.2013

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

Итак, если он работает в режиме выпуска, он не работает.

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

test* ptr = fun(); // return a pointer of type test
MyOwnAssert(ptr); 

void MyOwnAssert(void* pPointer)
{
   if (NULL == pPointer)
     abort();
}    
person VariOov    schedule 11.01.2013
comment
в приведенном выше коде вы проверяете NULL, а не утверждаете, и я думаю, что приведенный выше код можно упростить, используя MACRO вместо функции - person Astro - Amit; 11.01.2013

Как вы упомянули, assert используется только во время отладки, помогая программисту определить, где он пошел не так. Он не имеет ценности в производстве, поэтому я предпочитаю использовать второй метод, если у вас есть сомнения, что указатель может быть NULL.

person Kiran    schedule 11.01.2013
comment
да, я предпочитаю второй метод... но fun() в идеале не может возвращать NULL. Так что это не дополнительная проверка условий и не всегда играйте в более безопасную игру с безопасной стороной :-) - person Astro - Amit; 11.01.2013
comment
Но если у вас есть утверждение в отладке, вы никогда не будете тестировать путь кода, где указатель равен нулю. Это означает, что если это произойдет в рабочей среде, последующие пути кода никогда не будут проверены с нулевым указателем, и исходная ошибка может быть замаскирована последующим выполнением кода. Последующее выполнение кода может исправить ошибку, а может и нет - этот факт никогда не может быть проверен. - person CB Bailey; 11.01.2013
comment
@CharlesBailey Я не подозреваю, что значение указателя когда-либо будет NULL. - person Astro - Amit; 11.01.2013
comment
@ Amit0440: Мой комментарий был адресован KVRNKiran, когда он сказал, что предпочитает второй метод, если у вас есть сомнения, что указатель может быть NULL. - person CB Bailey; 11.01.2013

То, что вы делаете с assert, является вашим собственным выбором: вы можете использовать is в производстве, если хотите.

Я бы сказал, что использование assert() лучше, если вы хотите заранее обнаружить свои ошибки. Особенно, если тот факт, что это указатель NULL, не должен случаться.
Вы даже можете вставить Google Клавиша, так что всякий раз, когда вы нажимаете указатель NULL, вы отправляете отчет с полным стеком в этой точке.

В тех случаях, когда указатель NULL возможен (а иногда и ожидается...), я думаю, лучше использовать проверку NULL. Но я бы сказал, что на данный момент ваш код как-то неверен, если он должен приспосабливаться к передаваемым указателям NULL.

person Gui13    schedule 11.01.2013
comment
Можете ли вы подробно рассказать о Google Breakpad на небольшом примере? - person Astro - Amit; 11.01.2013