Утверждение используется для проверки чего-либо о состоянии вашей программы в определенный момент программы. Если утверждение не выполняется, значит, в программе есть ошибка, и нет смысла продолжать выполнение программы. Но стоит что-то стоит для запуска утверждения - особенно если оно включает вызовы функций - поэтому вы обычно отключаете их в режиме выпуска (-release
для dmd делает это автоматически). Вы запускаете свою программу и тестируете ее в режиме отладки, и, надеюсь, вы попадете в любые состояния, которые приводят к сбоям утверждений, чтобы вы могли отследить и исправить эти ошибки. Тогда вы надеетесь, что поймали их всех и что в режиме релиза ничего страшного не произойдет, если вы этого не сделали.
Но как насчет ввода путей кода, которые никогда не должны быть достигнуты при любых обстоятельствах? Вот тут и приходит assert(0)
.
Он работает как обычное утверждение без -release
, так что вы получите хорошие следы стека и все такое, когда вы нажмете на него, но потому что это то, что должно не только никогда не происходить, но и приводить к совершенно неверному пути кода, оно остается в режиме освобождения, но изменился на инструкцию по остановке. Классические места, где его можно использовать, например,
switch(var)
{
...
//various case statements that should cover all possible values of var
...
default:
assert(0, format("Invalid value for var: %s", var));
}
где регистр по умолчанию никогда не должен быть достигнут, и если это так, логика в вашей функции неверна, или
string func(int i) nothrow
{
try
return format("%s", i);
catch(Exception e)
assert(0, "Format threw. That should be impossible in this case.");
}
, где, если логика func
верна, для него должно быть невозможно выбросить, но это вызвало функцию, которую может выбросить при некотором наборе обстоятельств (только не этих), поэтому вы должны использовать блок try-catch, чтобы сделать компилятор счастливым. Затем вы кладете assert(0)
в блок catch, чтобы поймать его, если он действительно может throw.
Классический случай для assert(0)
фактически используется самим компилятором - то есть вставлять его в конец функции, которая не заканчивается оператором return, чтобы выполнение кода не пытается продолжить, если логика вашего кода неверна и вы все равно каким-то образом оказались в конце функции.
Во всех таких случаях вы имеете дело с путем кода, который невозможно найти, если ваш код корректен, но это защитная сеть на случай, если ваша логика неверна. Преимущества использования assert(0)
для этого по сравнению с инструкцией обнаженного останова состоят в том, что при включении -release
вы получаете правильную трассировку стека и можете получить хорошее сообщение об ошибке. Затем, когда -release
включен , он превращается в инструкцию остановки, поэтому вы гарантируете , что ваша программа не попадет в недопустимое состояние, пройдя строку с assert(0)
.
Вы используете обычные утверждения для материала, который вы хотите проверить в режиме отладки, но не в режиме выпуска, и вы используете assert(0)
для путей кода, которые вы хотите, чтобы гарантировано никогда не попадало в любой режим .