Чтение онлайн

на главную - закладки

Жанры

Кодеры за работой. Размышления о ремесле программиста
Шрифт:

Сейбел: К счастью, сейчас оборудование так не сыплется.

Томпсон: Да. Думаю, такие ошибки сейчас редки. К тому же сейчас компоненты гораздо более изолированы друг от друга: ошибку можно сделать, только если совсем уж безумствовать. Просто ошибиться на ассемблере: очень несложно что-то перепутать в каком-нибудь регистре при вызове подпрограммы. Но если вы имеете дело с высокоуровневым языком, где все аргументы должны подходить, такие ошибки становятся все более и более редкими.

Раньше в языках ассемблера их было множество. Если речь шла только о программах, а не о комбинации программ и оборудования, обычно они случались в одном месте и повреждалось только это место. Ошибка была с чем-то связана. Нужно

было сидеть и мониторить операционную систему. И часто — или очень часто — мы видели, что случалась ошибка, как можно быстрее останавливали процесс и смотрели, что происходит в других местах, таким образом отслеживая ошибки. Их можно было так поймать.

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

Сейбел: Сегодня некоторые говорят: «Да, конечно, у ассемблера больше всего шансов повредить память из-за программных ошибок, но и Си склонен к этому больше, чем некоторые другие языки». Можно сделать так, что указатели будут указывать черт знает куда, и получится выход за границу массива. Вы не считаете, что это проблема?

Томпсон: Нет, ее можно обойти языковыми оборотами. Некоторые пишут хрупкий код, а некоторые — очень крепкий структурно, и тут все зависит от человека. Думаю, хрупкий код можно написать на любом языке. Я определяю хрупкий код так: допустим, требуется добавить функциональность, так вот в хорошем коде ее нужно добавить только в одно место, а в хрупком придется затронуть сразу десять мест.

Сейбел: Если появляется брешь в безопасности из-за переполнения буфера, то что вы можете ответить на критику Си и C++, где утверждается, что они частично за это ответственны, что многих проблем можно было бы избежать, если использовать язык, который проверяет границы массивов или в котором есть сборка мусора?

Томпсон: Ошибки есть ошибки. Вы пишете код с ошибками, просто потому что вы так пишете. Если язык безопасен в смысле безопасности времени выполнения, то операционная система упадет, а не переполнит буфер, став при этом уязвимой. Например, ping of death — атака на IP-стек операционной системы. Мне кажется, что будут еще атаки такого рода. Это будут не атаки типа «полностью захватить машину и стать суперпользователем». Это будут ping of death.

Сейбел: Но ведь есть разница между отказом в обслуживании и уязвимостью, когда вы можете стать суперпользователем и делать, что захотите.

Томпсон: Есть две возможности стать суперпользователем: одна состоит в переполнении буфера, а другая — в том, чтобы указать программе сделать то, чего она делать не должна. В большинстве случаев реализуется вторая возможность, а не переполнение буфера. Вы можете стать суперпользователем без всяких переполнений. Так что ваш аргумент не работает. Все, что нужно сделать, — это уговорить su [73] дать вам оболочку; все пути и так уже там есть, без каких-либо ошибок времени выполнения.

73

Команда UNIX-подобных операционных систем, позволяющая пользователю войти в систему под другим именем. — Прим. науч. ред.

Сейбел: Ладно. Не будем говорить о том, что ведет к краху программы, уязвимости или чему-то подобному; есть такой класс ошибок, которые случаются в Си и C++, но почему-то не случаются, скажем, в Java. Есть ли для определенных типов приложений какие-то преимущества, весомые по сравнению с

тем, что эти ошибки будут происходить и вызывать неприятности?

Томпсон: Думаю, этот класс ошибок доставляет не так уж много проблем. Разумеется, каждый раз когда я пишу один из вызовов функции, которая не проверяет длину строки, strcpy и тому подобное, я знаю, что фактически пишу ошибку. Но каким-то образом я принимаю решение о том, оправданна ли эта ошибка, нужно ли экономить аргументы. Сейчас обычно я их экономлю. Но имеется семантическая проблема: если вы обрезаете строку и используете обрезанную строку, то появляется новая проблема. Ошибка по-прежнему там, просто буфер еще не переполнен.

Сейбел: Какие инструменты вы используете при отладке?

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

Сейбел: И что именно вы печатаете?

Томпсон: Все, что нужно, все, что удобно иметь под рукой. Инварианты. Но по большей части я печатаю во время разработки. Так я и выполняю отладку. Я не пишу программы с чистого листа — я беру программу и изменяю ее. Даже в большой программе я вывожу: «main, left, right, print, hello». Да, «hello» — это не то, что я ожидаю от этой программы. Я вывожу на печать то, что ожидаю увидеть, и отлаживаю эту часть. При разработке я запускаю программу двадцать раз в час.

Сейбел: Вы печатаете инварианты; а используете ли вы утверждения, которые проверяют эти инварианты?

Томпсон: Редко. Мне проще убедить себя, что они правильны, и либо закомментировать вывод на печать, либо отбросить их.

Сейбел: Почему же тогда вам проще напечатать, что инвариант верен, чем использовать assert для автоматической проверки?

Томпсон: Потому что при печати вы действительно видите, что происходит, а не частные значения, и вы печатаете к тому же много всего, не только инварианты. Просто я делаю вот так. Я не предлагаю это как общую парадигму. Но сам я всегда делаю так.

Сейбел: Когда мы говорили о том, как вы создаете программы, вы упоминали процесс разработки снизу вверх. Вы строите эти кирпичики отдельно друг от друга?

Томпсон: Иногда.

Сейбел: А вы пишете тестовые модули для тестирования низкоуровневых функций?

Томпсон: Да, я так часто поступаю. Все зависит от программы, над которой я работаю. Если программа — это транслятор из А в Б, то я предложу целый спектр возможных А и соответствующих Б. Для регрессионного тестирования исполню все варианты А и проверю, насколько им будут соответствовать Б. Компилятор, транслятор, поиск регулярных выражений. Что-то вроде этого. Но есть программы, которые совсем не похожи на эти. Я никогда много не занимался тестированием и в этих программах мало понимаю. Я проведу несколько проверок, но они редко будут значительными, потому что, например, их будет тяжело проводить внутри самой программы. Главным образом это будут просто регрессионные тесты.

Сейбел: Под более сложными для тестирования программами вы понимаете, например, драйверы устройств и сетевые протоколы?

Томпсон: Вообще, они ведь запускаются каждый раз, когда вы запускаете систему.

Сейбел: То есть, по-вашему, таким образом можно избавиться от части ошибок?

Томпсон: Да, конечно. Что может быть лучше для тестирования операционной системы, чем постоянно запускать ее?

Сейбел: Еще один важный аспект программирования — оптимизация. Одни приступают к оптимизации с самого начала. Другие предпочитают сначала написать код, а потом уже думать о дальнейшей оптимизации. Каков ваш подход?

Поделиться:
Популярные книги

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Душелов. Том 3

Faded Emory
3. Внутренние демоны
Фантастика:
альтернативная история
аниме
фэнтези
ранобэ
хентай
5.00
рейтинг книги
Душелов. Том 3

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5