ASSERT избыточен? - PullRequest
       9

ASSERT избыточен?

4 голосов
/ 24 декабря 2009
ASSERT(pointer);
pointer->x;

В этом коде ASSERT представляется избыточным. Если указатель НЕДЕЙСТВИТЕЛЕН, указатель-> х все равно не будет выполнен. Мой аргумент верен?

Ответы [ 7 ]

33 голосов
/ 24 декабря 2009

Важной (если не основной) целью утверждений является документ инвариантов, которые должны храниться в определенной точке кода. Тот факт, что assert может также прервать программу, если инвариант нарушен, просто обледенел, хотя и очень полезен. Я бы сказал, что в типичной программе 90% утверждений являются утверждениями, которые, очевидно, не могут потерпеть неудачу и никогда не потерпят неудачу. Другими словами, assert является в значительной степени своего рода формализованным языком комментариев. Формализовано в том смысле, что эти «комментарии» написаны на одном языке, а остальная часть кода написана на (C / C ++), а не на простом английском.

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

Что касается потока выполнения, assert всегда избыточен, поэтому утверждения, как правило, не компилируются в версии выпуска кода. Ничто не мешает вам сохранять утверждения в коде релиза, но обычно это делается путем введения особого вида «утверждения релиза». В любом случае, зависимость основных функций кода от действий, выполняемых утверждением, не является хорошей практикой программирования. Предполагается, что утверждения являются избыточными с точки зрения основной функциональности кода.

19 голосов
/ 24 декабря 2009

Да, но pointer->x потерпит неудачу (я полагаю) неконтролируемым образом, тогда как assert потерпит неудачу и скажет вам точно, где.

В некотором смысле, assert является всегда избыточным, конечно.

2 голосов
/ 24 декабря 2009

Нет, это не избыточно. Утверждение остановит выполнение до того, как произойдет что-то плохое. С другой стороны, если вы разыменуете недопустимый указатель, вы можете вызвать реальное повреждение или, по крайней мере, неконтролируемый segfault, а не контролируемый аборт.

0 голосов
/ 24 декабря 2009

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

void cpu_hog(int duration)
{
    int start_time = (int) time(NULL);
    int end_time   = start_time + duration;

    ASSERT(end_time > start_time);  /* If this fails, "int" is too small. */

    while ((int) time(NULL) < end_time)
        ;
}

Одно небольшое примечание: большинство сторонников ASSERT рекомендуют использовать его только для проверки предположений, которые вы делаете при написании кода (например, указатель не равен NULL или условие не может возникнуть). Обычно считается плохой идея использовать ASSERT для перехвата связанных с пользователем ошибок или исключений, которые могут произойти (например, переполнение диска), поскольку (1) ASSERT существует только в отладочной сборке и (2) даже если вы продвинете свой код отладки в производство, он будет аварийно завершать свою работу вместо того, чтобы корректно обработать условие.

0 голосов
/ 24 декабря 2009

ASSERT не является частью стандарта C, поэтому может быть что угодно

 #define ASSERT(x) do { \
     x = malloc ( sizeof *x ); \
     memset ( x, 0, sizeof *x );\
     } while ( 0 )

assert - это другое дело.

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

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

0 голосов
/ 24 декабря 2009

АССЕРТ не сбой. Это здесь, чтобы остановить отладчик на точке останова. Это не повлияет на сборку релиза.

0 голосов
/ 24 декабря 2009

В некоторых случаях assert можно использовать для отладки. http://simonwillison.net/2008/May/22/debugging/

...