Резюме к safe vs. unsafe
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 17.06.06 16:27
Оценка: 87 (10) +4 -7 :)))
Очередной раунд баталии, кажется, завершён, оглянемся.

Действующие лица и исполнители.

safe-тусовка — некий народ, вполне оформленно излагающий safe-"парадигму".
unsafe-тусовка — явной "парадигмы" не проповедует и на фоне предыдущих выглядит форменными анархистами.

Забавно, что именно "парадигму" в её википедическом толковании safe-тусовка и исповедует. Это действительно "взгляд", причём основательно замутнённый.

...

Главное, на мой взгляд, столкновение, произошло даже не на почве safe/unsafe. Этого противоречия по сути, не было даже в помине. Во всяком случае, unsafe-тусовка даже не пыталась сказать, что, на безопасность можно начхать и, скажем, лепить буфер произвольного размера.

Больше всего копий сломалось вокруг мелкой, по сути, задачи форматирования двух целых чисел константным форматом.

void func(int n, int v)
{
  char buffer[500];
  sprintf(buffer, "<c1>%d</c1><c2>%d</c2>", n, v);
    
  // что-то делаем с buffer
}


Главный аргумент safe-тусовки состоял в следующем: safe-правил нужно придерживаться всегда, ибо они правильные. Понятно, что о такую, замкнутую саму на себя аргументацию любая контраргументация разлетится вдребезги.

Любопытными оказались два момента, связанные с safe-правилами по отношению к языкам C/C++.

Первый: почему snprintf и прочие функции, контролирующие длину буфера (в дальнейшем — ФКДБ) a priori полагаются безопасными, тогда как sprintf и прочие подобные — нет?

Второй: почему выбор заведомо достаточного размера буфера без последующей проверки не считается safe-подходом?

Налицо двойной перекос в позиции safe-тусовки: первый — неправомерное сужение safe-методик C/C++ до ФКДБ; второй, следующий из первого — отрицание возможности использования якобы unsafe-механизмов. Никаких рациональных обоснований safe-тусовка так и не привела, вот потому я и сказал в самом начале о "взгляде", сиречь — о "парадигме". А как ещё называть сугубо иррационально обоснованные высказывания?

Первое противоречие простительно из-за того, что сходу подменили ФКДБ на некий общий safe. Я и сам время от времени сбивался из-за терминологической перекошенности.

А за второе противоречие я должен извиниться перед safe-тусовкой, поскольку сознательно не стал обращать на него внимание. Просто было интересно: догадаются или нет? Не догадались. Во всяком случае, я нигде подобного признания не прочёл. Может, ошибся. Как бы то ни было, обвинения меня и прочих оппонентов в "создании хаоса" не остановились, следовательно, safe-тусовка продолжает ассоциировать snprintf с однозначно надёжным стилем программирования.

На первый взгляд, аргументация safe-тусовки не кажется такой уж иррациональной. И правда, все упомянутые ими "может быть" могут быть и на самом деле. Только одна несуразица. Когда мы говорим о "может быть", нужно отдавать себе отчёт в том, что на самом деле быть может и чего не может в даном конкретном месте и времени. Многовато "может быть" на квадратный сантиметр, не правда ли?

Программирование и в самом деле окружено массой предрассудков, страхов, предостережений на ровном месте. В немалой степени этому способствуют разнообразные книги по поводу good practices. Авторы таких книг зачастую формулируют мысли так: "Мы изучили опыт N команд в M странах, и пришли к выводу, что strcpy — опасная вещь, потому что..." И после этого "потому что" текст может отсуствовать или может идти нечто невнятное. А из подобной литературы нередко запоминается только самое основное и краткое — вывод, но не предпосылки. И в пересказе получается так: "strcpy — плохо, потому что его использование влечёт массу неприятностей". Да и не только про strcpy такое говорят. Такие же ссылки я слышал и на высказывания Вирта про языки, и на Буча с его примерами классов и ещё на кучу других гранд-авторов компьютерной литературы.

Хотя у того же Буча целые главы посвящены тому, чтобы донести до сознания читателя: "Всё, что я сказал, имейте ввиду, но свою голову с плеч не снимайте". Почему об этом забывают? Не знаю. За всех сказать я тут ничего не могу. Могу только рассказать одну историю.

[история on]
В конце 90-х мне довелось участвовать в проекте биллинговой системы. В самой системе ничего особенного не было, даже биллинг оффлайновый. C++ под Win16 и Win32. Соответственно — ODBC, MFC, ATL. Однако, в коде периодически попадались вставки для Макинтоша...

Был тогда такой фетиш — многоплатформенность. Возможно, это были отголоски ещё недавних войн SCO Unix против Windows во имя мирового господства, возможно, связано с тогда ещё недавней миграцией с Win16 на Win32, а возможно, были и другие причины. Как бы то ни было, но многоплатформенность означала некую Незыблемую Правильность и Хороший Стиль.

Но эту программу никто на Макинтош переносить не помышлял. Даже 16-ти и 32-битная версии сильно отличались по своему строению (может, были какие-то небольшие общие куски, точно не помню). То есть ни о каком действительно многоплатформенном коде речи не шло. Небольшие различия для клонов 9x и NT, да и всё. Но тем не менее, вставки _MAC имели место быть.

Оказалось, что был один программист, который считал, что так будет правильно. Мол, нужно писать переносимый код. "Почему?" — спрашивали мы у шефа. "А он считал, что так надо. Вдруг, мол, будем на Макинтоше компилировать?", тут шеф хихикал в бороду: "Как этот Мак выглядит-то? Хоть кто-нибудь знает?"

В конце концов маковские дефайны остались в первых версиях исходников на SourceSafe. Жалеть, уж поверьте, не пришлось. Правильный подход в Хорошем Стиле, о котором с придыханием говорили гуру, закончился пшиком.
[история off]

Конечно, эта история ничего не доказывает. Стукнуло бы кому-нибудь в голову перенести программу на Mак, вот уж наигрались бы. Однако, история не знает сослагательного наклонения и главное, чуете родство моделей: "А так правильно... ибо вдруг..." Вот-вот, правильно чуете.

Тот же самый феномен я заметил и в оценках одиозного sprintf. Апофеозом мысли стало высказывание, что мол, если переполнение буфера может случиться, оно обязательно произойдёт. Нет, не произойдёт. Не потому, что пример нельзя переколпачить так, что вероятность переполнения увеличится, а потому, что в данном конкретном случае переполнения нет и оно не может случиться. Переколпакирование же — разговор отдельный, потому что изменённый код — это всегда новый код.

Возвращаясь к гранд-авторам компьютерной литературы, замечу, что то, что ими декларируется грешит излишней общностью, особенно, если это результаты исследований N команд. И их можно понять: представляете, какого размера были бы книги, если бы подробно излагались данные по каждому конкретному случаю? Поэтому такие выводы можно и должно учитывать, но вовсе не надо слепо переносить на каждый конкретный strcpy.

Это стало причиной моих язвлений по поводу "вредности чтения книг". Книги читать, конечно же, не вредно. Иногда — опасно. Опасно, когда харизма автора заслоняет rationale читателя. Опасно, когда чьё-то обобщённое наблюдение обращается в догму. Опасно, когда авторское "бывает" превращается в читательское: "точно будет!" Подчас из-за этого специалисты не пользуются огромными кусками инструментальных средств.

Причину такого ужесточения я могу только предположить: это желание иметь рецепт, который-всегда-работает. Желание окружить себя иллюзиями, что всё идёт "как надо" ибо "мы пользуемся правильными рецептами". Желание сие иррационально по существу: "Взял он три тысячи нужных вещей и уложил их на лодке своей." Вот вам проявление "парадигмы" в её худшей ипостаси. Освободите свой разум, коллеги, ну а ж... Смотрите "Взвод" в Гоблинской озвучке, или хотя бы вспомните: "Ведь для хорошего, для рыбака, удочка только нужна и река."

...

В заключение хочу поблагодарить активных участников.

Сначала оппонентов.

Дарнея — за невероятную настойчивость.
klapaucius-а — за неординарные формулировки.
VladD2 — за неожиданность.
WolfHound — за освежающие разговоры не по существу.

Теперь — пропонентов.

Cyberax — за последовательность.
eao197 — за спокойствие.
Kluev — за чёткость мысли.
McSeem2 — за угрюмость и совершенно шикарный "разнос" оппонента, у меня бы так не получилось.

А также остальных участников, перечислить коих нет ровно никакой возможности.

Разумеется, выражаю респект зачинщику — AlexLion. Правда, он почему-то растворился в пространстве.

Аплодисменты, занавес.
<< Под музыку: silent >>
<< При помощи Януса: 1.2.0 alpha rev. 650 >>

18.06.06 23:47: Перенесено из 'Философия программирования'
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.