Вопрос по c++, performance – Почему я должен использовать утверждения?

46

У меня никогда не было идей об утверждениях - зачем вам их использовать?

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

На тестах (в отладке) все было в порядке, но теперь мы хотим заняться гонками (релиз)! Должны ли мы отбросить всю безопасность, потому что при тестировании проблем не было?

Я никогда их не уберу. Я думаю, что большинство парней, которые утверждают, что удаление чего-либо, сопоставимого с утверждениями, никогда не профилировали их код, или утверждения были полностью смещены. Я никогда не видел реального преимущества в производительности, особенно в отношении правила 80/20.

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

Похоже, вы знаете, почему, вы просто не согласны. Это нормально :) Gareth Simpson
Джастин, это не то, что утверждает. Утверждения предназначены для сильного взрыва, когда происходит нечто, что буквально никогда не должно происходить (потому что это указывает на ошибку программирования). Они не предназначены для обработки ежедневных предсказуемых ошибок. Mike Daniels
Утверждения используются только ленивыми программистами, которые не хотят кодировать обработку ошибок. Если вы знаете, что ошибка возможна, обработайте ее. Если это невозможно, то нет оснований утверждать. Justin
У вас никогда не было идеи, и все же вы никогда не будете их удалять? Похоже, вы согласны и не согласны одновременно. ralphtheninja

Ваш Ответ

17   ответов
0

как программист использует API / функцию / класс / что угодно. Эти ошибки должны быть быстро исправлены во время отладки.

Для всего остального брось исключение.

-5

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

Кроме того, оставьте одно утверждение в своем коде, и закон Мерфи гарантирует, что он, в конечном счете, приведет к краху вашей программы. Я предпочитаю проверять данные, прежде чем выполнять их обработку и выдавать соответствующее исключение, чтобы они обрабатывались так же, как и любые другие исключительные состояния или операции. По моему опыту, это привело к созданию программного обеспечения, которое было гораздо более стабильным в долгосрочной перспективе с детерминированным поведением с точки зрения пользователя.

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

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

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

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

В большей части производственного кода, который я видел, я заметил в основном два способа справиться с этим: расточать утверждения по всему коду, а затем оставить хорошую кучу в производстве. Это вызывает бешеную тенденцию просто закрывать приложение для пользователя, мне еще предстоит увидеть, как Assert изящно отказывает системе ... он просто отказывает ей ... бум ... ушел ... конечный пользователь просто говорит & quot; WTF - ошибка подтверждения утверждения по адресу 0x330291ff !!! & quot;

Другой способ, даже самый худший, если вы спросите меня, состоял в том, чтобы просто поймать то, что было брошено, и спрятать это под ковром (когда-либо видел эти ужасные попытки с пустыми скобами !!)

НИ ПУТЬ будет работать, чтобы получить хорошую стабильную систему. Конечно, вы можете использовать утверждения в своем бета-коде и удалить их все в своем производственном коде ... но, черт возьми, вы уберете свои сети безопасности, потому что они производственные. Я был бы очень удивлен, что все эти проверки повредили бы производительность вашей системы.

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

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

так нет ... я не использую утверждения ... я использую исключения

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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededGOODError: User Rate Limit ExceededNOTError: User Rate Limit ExceededNOT OVERWRITINGError: User Rate Limit Exceeded
0

в котором утверждения явно влияли на производительность при включении. Проверка предварительных и постусловий математических функций, используемых графическим кодом в тесных циклах, например (функция квадратного корня возводит в квадрат свой результат и сравнивает его с входными данными и т. Д.). Конечно, это порядка нескольких процентных пунктов, но я написал код, который нуждался в этих нескольких пунктах.

Что еще более важно, я написал код, в котором утверждения вносили разницу в десятки процентов от размера кода. Когда объем памяти является проблемой, утверждения в коде выпуска, вероятно, являются недопустимым расточительством.

17

Использовать обработку ошибок для ожидаемых условий; используйте утверждения для условий, которые никогда не должны возникать. & quot;

Обычно цитируемый пример проверяет наличие нуля в знаменателе перед делением.

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

Модульные тесты не являются заменой утверждений.

Unit tests are not a replacement for assertions.Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
7

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

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

35

хорошая философская дискуссия по поводу использования исключений и утверждений в коде доставки, В конце,you're guarding against doing wild things when the program is in an irreparably broken state.

I believe, therefore, that when a program discovers something that is irrefutably wrong with its internal state, it is better off terminating at once, rather than giving its caller the opportunity to pretend that nothing is wrong.

If you like, I think that exceptions should be reserved for situations in which it is possible to do something sensible after catching the exception. When you discover a condition that you thought was impossible, it's hard to say much about what might happen afterward.

Error: User Rate Limit Exceededthe Internet Archive.
1

над которыми я работал, утверждения делались с помощью специального макроса, который по-разному работал в Debug и Release.

В Debug, если условие ложно, отладчик запускается в этой точке кода.

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

4

как и я, на самом деле предпочитают оставлять их в рабочем коде. Если ваша программа в любом случае пойдет на сорняки, у вас также может быть утверждение там, чтобы ваш клиент мог по крайней мере дать вам номер строки и имя файла (или любую информацию или действие, которое вы настраиваете для утверждения). Если вы пропустили утверждение, то все, что клиент мог сообщить вам, было: «Сбой».

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

0

a = set()
a.add('hello')
assert 'hello' in a

или же

a = 1;
assert a == 1; // if ram corruption happened and flipped the bit, this is the time to assert

Что касается исключений, то это то, с чем вы программно имеете дело:

while True:
  try:
    data = open('sample.file').read()
    break // successfully read
  except IOError:
    // disk read fail from time to time.. so retry
    pass

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

2

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

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

Это спорно ли утверждает, должны быть удалены с помощью использования макросов и т.п. в релизе, но и APOS; S, что было сделано в проектах, с которыми я работал на до сих пор.

0

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

0

0:

Прежде чем спуститься по крутому склону, как это, нужно всегда проверять свои сани на санях.
Правильно.
Ремень безопасности ? Никто.
Сигналы? Никто.
Тормоза? Никто.
Рулевое управление ? Никто.
WHEEEEEE

1

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

Это как этот код

int i = 1
i = i++ 

Обычный программист никогда не будет думать о том, что произойдет, если я буду отрицательным в последующем коде. Существует небольшая вероятность того, что ваш код вызовет переполнение, и языки, такие как java, перейдут с max int на min int, и вы получите очень большое отрицательное число. Это все случаи, которые вы обычно говорите. Э-э, этого никогда не случится. Но что делает ваша программа, если это произойдет? Поэтому, если вы знаете, что есть что-то, что, по вашему мнению, никогда не произойдет, проверьте это или против этого и вставьте ложное утверждение в предложение else, которое никогда не произойдет, вместо того, чтобы программировать оператор else. Таким образом, ваша программа должна полностью завершиться сбоем в тот момент, когда вы больше не уверены в том, что она делает. В рабочем коде должно быть что-то отличное от сбоя, например, информирование пользователя, сопровождающего, а затем выход.

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

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

1

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

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

A(char* p)
{
    if(p == NULL)
        throw exception;

    B(p);
    C(p);

}

B(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

C(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

D(char* p)
{
    assert(p != NULL);
    do stuff;
}

Вместо вызова & quot; if (p == NULL) выведите исключение; & quot; 5 раз, вы просто вызываете его один раз, так что вы уже знаете, что он не равен NULL при вводе B (), C () и D (). В противном случае утверждение завершится на этапе разработки, поскольку вы "изменили код!" не из-за "пользовательского ввода".

Это может заставить код работать намного быстрее в версии выпуска, потому что все, что вам нужно сделать, это вызвать gcc с & quot; -DNDEBUG & quot; поэтому все утверждения не будут скомпилированы и все «ненужные проверки» будут удалены в исполняемом файле.

2

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

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

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

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

Error: User Rate Limit Exceeded
3

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

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

40

can быть огромным В одном проекте наши утверждения буквально вызвали 3-кратное замедление. Но они помогли нам обнаружить некоторые действительно неприятные ошибки.

Какой именно смысл.

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

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

Что в основном сводится к следующему: «Зачем беспокоиться о перехвате ошибок, которые вы не можете обработать?»

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

I never got the idea of asserts -- why should you ever use them?

I mean, let's say I were a formula driver and all the asserts were things like security belt, helmet, etc.

Да, это хороший пример того, когдаnot использовать утверждение. Это вещи, которые на самом деле могут пойти не так во время выполнения, и которые должны быть проверены. Ваш водитель Формулы 1 может забыть о мерах предосторожности, и если он это сделает, мы хотим остановить все это прежде, чем кто-нибудь пострадает.

Но как насчет проверки, чтобы увидеть, что двигатель установлен? Нужно ли проверять это?during the race?

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

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

Это в основном разница. Существует исключение, чтобы помочь пользователю, обрабатывая ошибки, которые могут быть обработаны.

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

Квадратный корень из четырех суслаnever оцените до трех. Ошибка просто невозможна. Если это происходит, ваша логика программы просто нарушена. Неважно, сколько обработки ошибок мы обертываем вокруг этого, это то, что должно быть поймано во время разработки или нет вообще. Если мы использовали обработку исключений для проверки и обработки этой ошибки, что будет делать исключение? Сообщите пользователю, что программа в корне сломана. Никогда не используйте его?

Электронная почта от разработчика могла бы достичь этого. Зачем встраивать это в программный код? Это пример проблемы, которая просто не должна возникать. Если это произойдет, мы должны вернуться и исправить программу. Никакая другая форма обработки ошибок невозможна.

Но некоторые ошибки, такие как невозможность открыть файл для чтения,possible, Даже если это случится плохо, мы должны признать, что этоcan бывает. Поэтому мы должны справиться с этим, если это произойдет.

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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededduring testing/compilationError: User Rate Limit Exceededduring the raceError: User Rate Limit Exceededat run-timeError: User Rate Limit Exceededmust notError: User Rate Limit ExceededbeforeError: User Rate Limit ExceededbeforeError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededin the middle of the raceError: User Rate Limit ExceedednotError: User Rate Limit Exceeded
Error: User Rate Limit ExceededimpossibleError: User Rate Limit ExceededanyError: User Rate Limit Exceeded

Похожие вопросы