Иногда мне кажется что они правы (эти голоса, что раздаются со всех сторон, когда иду по супермаркету) :)
Во времена моей юности знакомые проводили эксперименты по выявлению устойчивости софта к искажению машкода - буквально брали скомпиленный код на x86 и вносили в прогу случайные искажения в случайных местах и смотрели что случится, и выяснили, что сишный код (ТурбоСи, который), из всего доступного в тот момент оказался самым устойчивым - под пиво входили в раж и в порядке хохмы заменяли тело случайной функции на сплошные нули - Си это спокойно переваривал, даже большинство программ продолжали устойчиво работать и выдавать предсказуемый результат. У всяких разных ТурбоПаскалей крыша ехала намного быстрей, ну а байткоду просто сразу будет жопа.
Еще на эту тему вспоминается, что я как любитель железа очень любил почитывать про отказоустойчивые системы, и не то чтобы сильно удивился, но не совсем без удивления читал про то как сильно пришлось изменить подход к радиационностойким процессорам при переходе от CISC к RISC, потому что ежели в классических (несуперскалярных) CISC было достаточно для радиационностойкости защитить центральный пайплайн, который исполняет микропрограмму (а остальное там дубовое - что там например масочному ROM с микропрограммой сделается), то в RISC уже нужно было защищать намного больше, потому что состояние размазано по множеству узлов.
И вот видя как народ код пишет (в том числе и даже в особенности компиляторы), у меня временами буквально волосы на 5-й точке шевелятся, как подумаю, как этот ужас будет исполнять мой функциональный код..
Ну то есть я хочу сказать, что процедурный/объектный код просто работает на другом подмножестве состояний системы чем функциональный, и пока функциональный код встречается относительно редко, непонятные проблемы будут стабильно вылезать.
Ваш способ проверки устойчивости вызывает больше вопросов, чем предоставляет ответов.
В реальности вероятность сбоя маленькая, хотелось бы увидеть прикидку, по которой разница количества битов в разы меняет вероятность сбоя на проценты.
Зарисовывание функций нолями не означает устойчивость остальной программы к неверному результату функции. Если её забить нолями всю, т.е. включая ret, то в итоге выполняться будет следующая за ней функция в сегменте кода. А тут уже как карта ляжет - Сишная функция даст сбой в точке возврата, но в остальном останется рабочей. В Паскале функция даст не только сбой в точке возврата, но и стек подотрёт по-другому; а вот тут уже всякие кони будут проявляться и в функциях, вызванных позже.
Это совершенно правильный способ. В реальной жизни именно так и происходит, что сбоят с некоторой вероятностью отдельные ячейки памяти.
Вероятность что сбой подотрет именно ret очень низка.
Да, специфика подтирания стека в Паскале приводит к тому, что всего одна сбойная ячейка приводит к множественным сбоям в разных местах системы, то есть в Си сбой ячейки это не более чем сбой одной ячейки, а в Паскале сбой всего одной ячейки с ненулевой вероятностью порождает сразу целый каскад сбоев.
В "реальной жизни" считать такое поведение нормальным (или, тем более, превозносить) это или запредельная смелость, или откровенная глупость. С момента сбоя ячейки поведение не определено вообще. Я предпочту доверить свою жизнь херне, которая как можно быстрее упадёт и перезапустится, а не будет творить что-то непредсказуемое.
Сишный код использует ТАКОЕ подмножество кода процессора, что всё состояние системы даже не компактно расположено - его фактически просто нет в классическом Си. Виртмашины практически все активно используют сложные структуры данных, спагетти из кода с данными (виртмашину по-определению пишут непроцедурно), самомодифицирующийся код. - Если не делать самомодификацию кода, и держать все данные компактно в статическом месте, отдельно от исполняемого кода, и конечно не использовать хип (чисто стек), тогда байткод не будет по надежности отличаться от Сишного кода.
Ну, это байка для "настоящие программисты пишут на си". В реальности, существуют методы восстановления информации при потере её части. Вопрос только в их реализации на уровне транслятора.
Да ну, несерьзно это. Есть теория кодирования, её методы позволяют восстановить информацию в канале. Если вы о надежности систем (сбои памяти), то это, опять же, решается другими методами. Говорить о том, что программа на Си чем-то лучше других сродни утверждению что "Жигули"-копейка надежнее нового напичканного электроникой "Мерседеса" с автоматической коробкой, потому что у "жигуля" устройство проще. Как минимум, куча уязвимостией программ на Си связана с переполнением буфера, невозможном (теоретически) в той же Ява-машине.
Я не говорил что Си-программа лучше - она всего навсего ведет себя более предсказуемо. А что касается сравнения "к\опейки" с мерседесом, то вобщем в случае равного качества исполнения так оно и есть - более простые системы действительно надежнее. Естественно, в случае компьютера код сам по себе является системой, имеющей потенциальные проблемы, но в случае если надежность кода примерно одинакова, система на Си выиграет по надежности у системы на Java.
Всё очень серьезно. В разработке отказоустойчивых систем есть понятие "точка отказа", так вот обычно это выглядит, что есть некоторое количество ненадежных узлов, которые могут дублироваться/корректироваться, и есть сверхнадежные узлы, вероятность сбоя которых принципиально исчезающе мала, и вот эти сверхнадежные узлы и делают собственно коррекцию, и коммутируют ненадежные узлы (отключают отказавшие, подключают резервные).
Физически это выглядит так, что например в современном спутнике стоит несколько компьютеров (обычно от 2-х до 4-х), также продублирована часть других систем (двигатели, всяческая механика, обогреватели, обычно стоят парами или даже тройками, электропитание проведено 3+ проводами), и стоят совершенно дубовые коммутаторы, и стоит также совершенно дубовая, но очень надежная так-называемая "релейная" система управления (иногда и не одна), у которой отдельный радиоканал, и эта система позволяет управлять коммутаторами, а также подключена к аппаратным отладчикам всех компьютеров, и может каждый из этих компьютеров включить/выключить/резетнуть, а также как стандартный отладчик, остановить исполнение, запустить исполнение с другой точки, изменить значение каких-то ячеек памяти, итп. Плюс сам спутник делается таким образом, что в случае прекращения действия двигателей, он под действием космических факторов через некоторое время сам поворачивается к земле правильной стороной.
Например, в коде на классическом Си есть жесткое разделение исполняемого кода и данных, поэтому можно хранить код в отдельной памяти, и сделать сверхнадежными сам процессор, память стека, и устройство хранения кода, а память данных сделать ненадежной, и при каждом обращении к памяти данных, делать коррекцию ошибок. То же можно сделать и с системой на других языках, и с виртмашинами, но просто точек отказов станет намного больше.
Какое отношение имеет язык Си к тому, как менеджер памяти управляет её распределением? Или вы ограничиваетесь программами, оперирующими только статической памятью? Сегменты кода и данных существуют при любой компиляции в родной код. А в гарвардской архитектуре память программ и данных разделена явно. Опять же, гарвардская архитектура и язык Си - это малосвязанные вещи.
В разработке безопасных программ распределение кода и данных компилятором имеет далеко не первый приоритет. И язык Си здесь далеко не в лидерах.
> Или вы ограничиваетесь программами, оперирующими только статической памятью?
Не я, а конкретно данный случай.
> Сегменты кода и данных существуют при любой компиляции в родной код.
Нет. Это специфика процессоров с изначально ограниченной адресацией и затем расширенной, как x86 - нампример на m68k очень популярно кодировать всё подряд, в смысле лапшой, и использовать самомодифицирующийся код. Ну также сегментацией специфичны бизнес системы, тоже не всегда из безопасности, а часто от наследования старого кода.
> В разработке безопасных программ распределение кода и данных компилятором имеет далеко не первый приоритет.
Вы просто очень мало знаете про реальность разработки отказоустойчивых систем.
та в ваших схоластических кругах любой - лох, кто не из ваших схоластических кругов
а снаружи - ну секта и секта
сами себя замкнули в парадигме скрещивания ежей с ужами - а потом с героическим привлечением горних атсральных сущностей разруливаете проблемы с неизменно получающейся колючей проволокой
если еще короче: как-то выделять монады-хренады в инженерии не нужно монады побриты бритвой Оккама
no subject
Date: 2014-07-16 05:10 am (UTC)Я в обоих случаях вижу лохов, не употребляющих монад.
no subject
Date: 2014-07-16 07:20 am (UTC)Во времена моей юности знакомые проводили эксперименты по выявлению устойчивости софта к искажению машкода - буквально брали скомпиленный код на x86 и вносили в прогу случайные искажения в случайных местах и смотрели что случится, и выяснили, что сишный код (ТурбоСи, который), из всего доступного в тот момент оказался самым устойчивым - под пиво входили в раж и в порядке хохмы заменяли тело случайной функции на сплошные нули - Си это спокойно переваривал, даже большинство программ продолжали устойчиво работать и выдавать предсказуемый результат.
У всяких разных ТурбоПаскалей крыша ехала намного быстрей, ну а байткоду просто сразу будет жопа.
Еще на эту тему вспоминается, что я как любитель железа очень любил почитывать про отказоустойчивые системы, и не то чтобы сильно удивился, но не совсем без удивления читал про то как сильно пришлось изменить подход к радиационностойким процессорам при переходе от CISC к RISC, потому что ежели в классических (несуперскалярных) CISC было достаточно для радиационностойкости защитить центральный пайплайн, который исполняет микропрограмму (а остальное там дубовое - что там например масочному ROM с микропрограммой сделается), то в RISC уже нужно было защищать намного больше, потому что состояние размазано по множеству узлов.
И вот видя как народ код пишет (в том числе и даже в особенности компиляторы), у меня временами буквально волосы на 5-й точке шевелятся, как подумаю, как этот ужас будет исполнять мой функциональный код..
Ну то есть я хочу сказать, что процедурный/объектный код просто работает на другом подмножестве состояний системы чем функциональный, и пока функциональный код встречается относительно редко, непонятные проблемы будут стабильно вылезать.
no subject
Date: 2014-07-16 09:05 am (UTC)no subject
Date: 2014-07-16 03:53 pm (UTC)no subject
Date: 2014-07-16 04:11 pm (UTC)В реальности вероятность сбоя маленькая, хотелось бы увидеть прикидку, по которой разница количества битов в разы меняет вероятность сбоя на проценты.
Зарисовывание функций нолями не означает устойчивость остальной программы к неверному результату функции. Если её забить нолями всю, т.е. включая ret, то в итоге выполняться будет следующая за ней функция в сегменте кода. А тут уже как карта ляжет - Сишная функция даст сбой в точке возврата, но в остальном останется рабочей. В Паскале функция даст не только сбой в точке возврата, но и стек подотрёт по-другому; а вот тут уже всякие кони будут проявляться и в функциях, вызванных позже.
no subject
Date: 2014-07-16 04:40 pm (UTC)Вероятность что сбой подотрет именно ret очень низка.
Да, специфика подтирания стека в Паскале приводит к тому, что всего одна сбойная ячейка приводит к множественным сбоям в разных местах системы, то есть в Си сбой ячейки это не более чем сбой одной ячейки, а в Паскале сбой всего одной ячейки с ненулевой вероятностью порождает сразу целый каскад сбоев.
no subject
Date: 2014-07-16 07:27 pm (UTC)no subject
Date: 2014-07-16 11:00 pm (UTC)no subject
Date: 2014-07-16 09:08 am (UTC)no subject
Date: 2014-07-16 04:02 pm (UTC)Виртмашины практически все активно используют сложные структуры данных, спагетти из кода с данными (виртмашину по-определению пишут непроцедурно), самомодифицирующийся код.
- Если не делать самомодификацию кода, и держать все данные компактно в статическом месте, отдельно от исполняемого кода, и конечно не использовать хип (чисто стек), тогда байткод не будет по надежности отличаться от Сишного кода.
no subject
Date: 2014-07-16 11:14 am (UTC)В реальности, существуют методы восстановления информации при потере её части.
Вопрос только в их реализации на уровне транслятора.
no subject
Date: 2014-07-16 03:54 pm (UTC)no subject
Date: 2014-07-16 05:58 pm (UTC)Если вы о надежности систем (сбои памяти), то это, опять же, решается другими методами.
Говорить о том, что программа на Си чем-то лучше других сродни утверждению что "Жигули"-копейка надежнее нового напичканного электроникой "Мерседеса" с автоматической коробкой, потому что у "жигуля" устройство проще.
Как минимум, куча уязвимостией программ на Си связана с переполнением буфера, невозможном (теоретически) в той же Ява-машине.
no subject
Date: 2014-07-16 11:07 pm (UTC)А что касается сравнения "к\опейки" с мерседесом, то вобщем в случае равного качества исполнения так оно и есть - более простые системы действительно надежнее.
Естественно, в случае компьютера код сам по себе является системой, имеющей потенциальные проблемы, но в случае если надежность кода примерно одинакова, система на Си выиграет по надежности у системы на Java.
no subject
Date: 2014-07-16 11:45 pm (UTC)Физически это выглядит так, что например в современном спутнике стоит несколько компьютеров (обычно от 2-х до 4-х), также продублирована часть других систем (двигатели, всяческая механика, обогреватели, обычно стоят парами или даже тройками, электропитание проведено 3+ проводами), и стоят совершенно дубовые коммутаторы, и стоит также совершенно дубовая, но очень надежная так-называемая "релейная" система управления (иногда и не одна), у которой отдельный радиоканал, и эта система позволяет управлять коммутаторами, а также подключена к аппаратным отладчикам всех компьютеров, и может каждый из этих компьютеров включить/выключить/резетнуть, а также как стандартный отладчик, остановить исполнение, запустить исполнение с другой точки, изменить значение каких-то ячеек памяти, итп.
Плюс сам спутник делается таким образом, что в случае прекращения действия двигателей, он под действием космических факторов через некоторое время сам поворачивается к земле правильной стороной.
Например, в коде на классическом Си есть жесткое разделение исполняемого кода и данных, поэтому можно хранить код в отдельной памяти, и сделать сверхнадежными сам процессор, память стека, и устройство хранения кода, а память данных сделать ненадежной, и при каждом обращении к памяти данных, делать коррекцию ошибок.
То же можно сделать и с системой на других языках, и с виртмашинами, но просто точек отказов станет намного больше.
no subject
Date: 2014-07-17 09:01 am (UTC)Сегменты кода и данных существуют при любой компиляции в родной код.
А в гарвардской архитектуре память программ и данных разделена явно.
Опять же, гарвардская архитектура и язык Си - это малосвязанные вещи.
В разработке безопасных программ распределение кода и данных компилятором имеет далеко не первый приоритет. И язык Си здесь далеко не в лидерах.
no subject
Date: 2014-07-17 01:43 pm (UTC)Не я, а конкретно данный случай.
> Сегменты кода и данных существуют при любой компиляции в родной код.
Нет. Это специфика процессоров с изначально ограниченной адресацией и затем расширенной, как x86 - нампример на m68k очень популярно кодировать всё подряд, в смысле лапшой, и использовать самомодифицирующийся код.
Ну также сегментацией специфичны бизнес системы, тоже не всегда из безопасности, а часто от наследования старого кода.
> В разработке безопасных программ распределение кода и данных компилятором имеет далеко не первый приоритет.
Вы просто очень мало знаете про реальность разработки отказоустойчивых систем.
no subject
Date: 2014-07-16 10:05 pm (UTC)а снаружи - ну секта и секта
сами себя замкнули в парадигме скрещивания ежей с ужами - а потом с героическим привлечением горних атсральных сущностей разруливаете проблемы с неизменно получающейся колючей проволокой
если еще короче: как-то выделять монады-хренады в инженерии не нужно
монады побриты бритвой Оккама