Дневник еще одного неудачника


Previous Entry Share
Оптимизацияя в компиляторах и безопасность.
geov
Можно и не обладая глубоким умом писать так,
что другому понадобится много ума, чтобы понять написанное.
Лихтенберг Георг Кристоф

Увидев в rss заголовок из опеннета обратил внимание. Я иногда пищу всякие там драйверы и проверок в них просто немерено и еще ничего не вырезалось. Я конечно ожидал мног настоящих багов (например gcc из Xilinx ISE умеет собирать код для powerpc только если включить -O2 иначе все глючит, падает и не работает). Вообще хотелось бы полные примеры а не огрызки которые там написаны..

Ну первый пример из PDF достаточно оригинален и да, компилятор действительно поступает по стандарту (§6.5.6/p8). И написано там нечто вроде:

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

Т.е. компилятор вообще говоря действует по стандарту и нечего на зеркало пенять. Однако вопрос в другом. Мне всегда казалось что надо сравнивать два условия на манер (buf_end>buf) && (buf_end-buf>len). Это, насколько я знаю, вполне определено по стандарту и гораздо понятнее. Кроме того если buf_end априори больше buf то первую проверку можно опустить. Мы все математики черт возьми, мы же знаем как считается расстояние.

Второй пример не менее интересен и фееричен. Если вы написали кривую программу в таком виде, а вы ее наверняка и warning от компилятора получили, то пенять на то что оптимизатор что-то там вырезал как-то глупо. И вдвойне обидно что современный стандарт си позволяет объявление переменных в любом месте (если вы пользуетесь MSVC то я прекрасно понимаю как вам больно это слышать) и разыменование указателя до проверки его валидности это както неправильно, хотя говорят разработчики ядра Linux любят так делать.

Вообще довольно интересно что многие баги оаписанные далее возникли не просто так а из попытки применить какието битхаки с переполнением, которое вообще говоря нормально определено только для беззнаковых целых и в других случаях поведение декларируется как всякие там undefined и implementation defined (а это еще большая головная боль).

Пишите понятный код, и компилятор вас поймет.

?

Log in