@ dmckee
Ну, это не вписывается в комментарий, но вот в чем дело:
Сначала вы пишете правильный статический анализатор. «Правильный» в данном контексте означает, что он не будет хранить молчание, если в анализируемом коде есть что-то сомнительное, поэтому на этом этапе вы весело объединяете неопределенные и неуказанные поведения. Они оба плохие и неприемлемые в критическом коде, и вы правильно предупредите их обоих.
Но вы хотите предупредить только один раз об одной возможной ошибке, а также знаете, что ваш анализатор будет оцениваться в тестах с точки зрения «точности» и «отзыва» по сравнению с другими, возможно, не правильными, анализаторами, поэтому вы не должен дважды предупреждать об одной и той же проблеме ... Будь то истинная или ложная тревога (вы не знаете, какая. Вы никогда не знаете, какую, иначе это было бы слишком легко).
То есть вы хотите выдать одно предупреждение для
*p = x;
y = *p;
Поскольку, как только p
является действительным указателем на первый оператор, его можно считать действительным указателем на второй оператор. И если вы не сделаете вывод, это снизит ваш счет по метрике точности.
Таким образом, вы учите свой анализатор предполагать, что p
является действительным указателем, как только вы предупредили об этом в первый раз в приведенном выше коде, так что вы не будете предупреждать об этом во второй раз. В более общем смысле вы учитесь игнорировать значения (и пути выполнения), которые соответствуют тому, о чем вы уже предупреждали.
Затем вы понимаете, что не так много людей пишут критический код, поэтому вы проводите другие облегченные анализы для остальных из них, основываясь на результатах первоначального, правильного анализа. Скажем, слайсер программ на Си.
И вы говорите «им»: вам не нужно проверять все (возможно, часто ложные) сигналы тревоги, сгенерированные при первом анализе. Программа нарезки ведет себя так же, как и исходная программа, если ни одна из них не запущена. Слайсер создает программы, эквивалентные критерию нарезки для «определенных» путей выполнения.
А пользователи весело игнорируют сигналы тревоги и используют слайсер.
И тогда вы понимаете, что, возможно, есть недоразумение. Например, большинство реализаций memmove
(вы знаете, тот, который обрабатывает перекрывающиеся блоки) фактически вызывает неопределенное поведение при вызове с указателями, которые не указывают на один и тот же блок (сравнивая адреса, которые не указывают на один и тот же блок). А ваш анализатор игнорирует оба пути выполнения, потому что оба не определены, но в действительности оба пути выполнения эквивалентны и все хорошо.
Таким образом, не должно быть никакого недопонимания в отношении значения сигналов тревоги, и если кто-то намерен их игнорировать, следует исключить только безошибочное неопределенное поведение.
И вот как вы в конечном итоге сильно интересуетесь различием между неопределенным поведением и неопределенным поведением. Никто не может обвинить вас в игнорировании последнего. Но программисты напишут первое, даже не задумываясь об этом, и когда вы скажете, что ваш слайсер исключает «неправильное поведение» программы, они не будут чувствовать, что они обеспокоены.
И это конец истории, которая определенно не вписалась в комментарий. Приносим извинения всем, кто читал это далеко.