Согласно стандарту С++ (5/5) деление на ноль является неопределенным поведением. Теперь рассмотрим этот код (множество бесполезных операторов, чтобы компилятор не оптимизировал код):
int main()
{
char buffer[1] = {};
int len = strlen( buffer );
if( len / 0 ) {
rand();
}
}
Visual C++ компилирует оператор if
следующим образом:
sub eax,edx
cdq
xor ecx,ecx
idiv eax,ecx
test eax,eax
je wmain+2Ah (40102Ah)
call rand
Ясно, что компилятор видит, что код должен делить на ноль - он использует шаблон xor x,x
для обнуления ecx
, который затем служит вторым операндом в целочисленном делении. Этот код определенно вызовет ошибку «целочисленное деление на ноль» во время выполнения.
IMO такие случаи (когда компилятор знает, что код всегда будет делить на ноль) стоят ошибки времени компиляции - Стандарт этого не запрещает. Это помогло бы диагностировать такие случаи во время компиляции, а не во время выполнения.
Однако я поговорил с несколькими другими разработчиками, и они, кажется, не согласны — их возражение: «Что, если автор захочет разделить на ноль, чтобы… эмм… проверить обработку ошибок?»
Преднамеренное деление на ноль без ведома компилятора не так уж сложно - с помощью декоратора функций __declspec(noinline)
Visual C++:
__declspec(noinline)
void divide( int what, int byWhat )
{
if( what/byWhat ) {
rand();
}
}
void divideByZero()
{
divide( 0, 0 );
}
который гораздо более читабелен и удобен в сопровождении. Эту функцию можно использовать, когда ему «нужно протестировать обработку ошибок», а во всех остальных случаях получить приятную ошибку времени компиляции.
Я что-то упускаю? Нужно ли разрешать выброс кода, который, как известно компилятору, делится на ноль?