Страницы

Проблема не в C, а в разработчиках?

Язык C имеет славу крайне небезопасного языка. Так ли это на самом деле?

Хотя язык C и плох во многих отношениях, он не так плох, как мог бы быть. Как известно, язык C появился, когда Денис Ритчи работал над компилятором языка B, который был куда хуже. Эволюционные улучшения, которые Ритчи вносил в язык по ходу работы, и послужили основой для нового языка.

А вот стандарт языка C, если оставить за скобками предмет стандартизации, составлен весьма неплохо. Достаточно точно описывая неопределённое поведение, которое многие ошибочно приписывают к недостаткам языка, стандарт создаёт основу для возможности создания компилятора, позволяющего проверять не только отсутствие нарушения печально известных ошибок памяти, но и такие логические ошибки, которые другие, якобы более безопасные языки, обязывают оставить без внимания.

Такая возмность не является чисто гипотетической, она давно воплощена в ведущих компиляторах языка. Пусть и не идеальное, но достаточно хорошее воплощение защиты можно применять не только в отладочных целях, но оставлять её в выпускных версиях программ. Отсутствие надёжной защиты является не неизбежным следствием языка C, а вопросом выбора разработчиков и сопровождающих. И что же они выбирают в массе своей? Они выбирают всё выключить, оставляя только наименее затратные по скорости защиты, но которые также неполны и недостаточно надёжны.

Я хотел посмотреть, нельзя ли исправить это положение дел со стороны пользователя? Для этого я воспользовался дистрибутивом GNU/Linux NixOS, позволяющим в конфигурации добавить нужные настройки компилятора в пакет, не меняя самого пакета. Это действительно сработало, но опыт выявил, что большое количество пакетов либо после этого работают некорректно, например, bash, либо даже не собираются из-за проваливающихся тестов или падающей кодогенерации, например, glibс. А ведь это одни из важнейший частей системы, которые должны были проверяться с особой тщательностью. На деле, эти программные коды не то, что не собираются с защитами, что вполне ожидаемо, но даже не тестируются с ними, что уже выглядит проявлением большой глупости.

Любое воплощение неопределённого поведения не меняет поведение правильно выполняющегося кода. Оно меняет поведение только кода, нарушающего обоснованные правила языка и именно поэтому это должно проверяться. Рарзработчики же часто считают, что если они заставили методом тыка работать неправильный код ожидаемым для них способом, то всё в порядке. И если что-то всё равно указывает на наличие проблемы, то именно оно эту проблему и создаёт. Если проверку выключить, то и проблемы «не станет».

Естественно, мой опыт на этом завершиля, потому что превращаться в сопровождающего практически всего наследия Linux у меня нет никакого желания. Здесь нужна системная робота со стороны всех участников.

Единственным светлым пятном на этом фоне оказалось само ядро Linux. Ядро требует особого подхода, поэтому включить обычные проверки для него не представляется возможным. Тем не менее вся работа по их внедрению уже проведена, и пусть по-другому, проверки можно включить. Я не был уверен, что смогу хотя бы загрузиться, но на удивление ядро показало стабильную работу длительное время. Это многое проясняет.

Комментариев нет:

Отправить комментарий