Почему gcc не выдает предупреждение при неопределенном поведении в коде внутри?
Я только что прочитал этот FAQ по C++ о неопределенном поведении и точках последовательности и немного поэкспериментировал. В следующем коде gcc-4.5.2
выдает предупреждение только в строке, упомянутой в комментарии к коду, хотя предыдущая строка тоже показывает неопределенное поведение, не так ли? Вы не можете сказать, какой операнд сложения выполняется первым (как +
не точка последовательности). Почему gcc тоже не выдает предупреждение в этой строке?
int i=0;
int j=0;
int foo(void) {
i=1;
return i;
}
int main(void) {
i = i + foo();
j = j + (j=1); //Here is a rightly warning
return 0;
}
Спасибо за помощь.
3 ответа
Поведение i = i + foo(); не указано, но не определено Undefined означает, что разрешено любое возможное поведение, даже прерывание программы. Unspecified означает, что либо i вычисляется первым, либо foo(). Да, foo пишет в тот же i, но, поскольку это происходит в отдельном операторе, существует точка последовательности до и после этого хранилища.
Линия i = i + foo();
в вашей программе не указано, но не определено.
Компиляторы пытаются выдавать предупреждения без ложных срабатываний (каждый раз, когда предупреждает компилятор, есть дефект, который должен исправить программист), или, по крайней мере, с очень низким уровнем ложных срабатываний. Это значит, что взамен у них немало ложных негативов. В соответствии с той же философией, компиляторы обычно не предупреждают о неопределенном поведении.
Чтобы получить предупреждение о вашей программе, вы должны посмотреть на статические анализаторы, которые более агрессивны в отношении предупреждений, за счет немного большего количества ложных срабатываний. Статические анализаторы могут очень хорошо решить, чтобы предупредить о неопределенном поведении. Некоторые из них даже предупреждают об определенных поведениях, которые, хотя и определены, указывают на то, что программист, вероятно, был сбит с толку.
Людям видно, что вызов foo() изменит i, но для компьютерной программы это трудно увидеть. Это просто не предназначено, чтобы увидеть это.