Что такое стратегия, если утверждение не удается

StackOverflow https://stackoverflow.com/questions/4049351

  •  27-09-2019
  •  | 
  •  

Вопрос

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

Например,

void f(int *p)
{
  assert(p);
  p->do();
}

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

void f(int *p)
{
  assert(p);

  if (p)
  {
    p->do();
  }
}

В конце концов, утверждение означает, что тесты условия никогда не должны быть ложными. Но если, если мы не проверяем это, и не удается, программа сбои. Звучит как дилемма. Как вы, ребята, имеете дело с этим?

Это было полезно?

Решение

Если утверждение не удается, Программа должна сбой.

Утверждение, а утверждение означает, что программист сделал фундаментальную ошибку в понимании того, как продвижение программ будет продолжаться. Это помощь в целях развития, а не производственная помощь. В производстве можно справиться исключения, Как они «могут» происходят, тогда как утверждения должны «никогда» не провалиться.

Если вы в лагере, который говорит: «О, но что, если утверждения терпят неудачу в производстве? Мне нужно поймать их!» Тогда вы не хватаете точкой. Спросите себя, в таком случае, Почему вы не просто бросаете исключение (или иным образом обрабатывать ошибку)?

Вообще говоря, утверждать является нет Просто сокращение для «если условие не встречало, бросайте исключение» (ну, иногда это оперативная семантика, но это не денотационная семантика). Скорее, неспособность утверждения означает, что приложение находится в Государство Разработчик не верит, даже возможно. Отказ Вы действительно хотите, чтобы код продолжить выполнение в таком случае? Ясно (я бы сказал), Нет.

Другие советы

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

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

Однако один важный момент - утверждения также часто используются для выявления основных проблем с целостностью ваших данных. Если вы продолжаете мимо этих утверждений, вы можете рисковать развращенными данными. В этих случаях может быть лучше сбой, а не разрушать ваши данные. (Очевидно, что любой хвостный обработчик, который, по крайней мере, поднимает разумный интерфейс с описанием ошибки, будет предпочтительным).

Строго говоря, второй код имеет избыточность.

void f(int *p)
{
  assert(p);
  if (p)    // Beats the purpose of assertion
  {
    p->do();
  }
}

Утверждение означает ошибку произошла. Что-то неожиданное / необработанное. В вышеуказанном коде, либо

1) Вы правильно обрабатываете случай, когда P - NULL. (Не вызывая P-> DO ()) - что предположительно является правильным / ожидаемым, что нужно сделать. Тем не менее, тогда утверждение является ложная сигнализация.

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

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

Что сказал, некоторые люди любят лечить утверждать, как что-то пошло не так, но давайте посмотрим, все ли мы получим правильный вывод. Отказ ИМО, это плохую стратегию и создает путаницы во время исправления ошибок.

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

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

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

Утверждения полезны для отладки, как вы упомянули. Они никогда не должны вносить его в производственный код (как скомпилированы, все в порядке, чтобы обернуть их в #ifdefs конечно)

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

void f(int *p)
{

  if (!p)
  {
    do_error("FATAL, P is null.");
  }

  p->do();
}

Где do_error - это функция, которая регистрирует ошибку и чисто выходит.

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

Не вкладывайте много усилий в обработке исключения. Просто убедитесь, что вы можете получить полное исключение, включить Gacktrace. Который применяется к выпуску à, в частности.

Поскольку многие люди комментируют утверждения в режиме выпуска:

В том, что я работаю, эффективность очень важно (иногда, выполнение на больших наборах данных занимает десятки часов до нескольких дней для завершения). Следовательно, у нас есть специальные макросы, которые утверждают только в коде отладки (запущены во время qa etc). В качестве примера, утверждение внутри A для цикла, безусловно, является накладным расходом, и вы можете избежать его в коде выпуска. В конце концов, если все IZ хорошо, утверждения не должны потерпеть неудачу.

Одним из примеров, где «Выпуск кода» - это хорошо, является - если логика не должна ударить определенную ветку кода вообще. В этом случае Assert (0) в порядке [при этом любой вид Assert (0) всегда может быть оставлен в коде выпуска].

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top