Автор Тема: Безопасность и Си.  (Прочитано 11390 раз)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Безопасность и Си.
« : Январь 14, 2014, 08:09:55 pm »
Что-то у нас тут клеветы только на Оберон. Пора бы разбавить. Так что теперь про Си будет (нет. не про С++, хотя к нему частично тоже применимо, особенно если разработчиков давно плетьми не драли и они продолжают писать код в стиле Си).

Собственно сама история описана тут: http://habrahabr.ru/post/198836/

Если кратко - из за того, что в Сях есть две вещи:
1) взятие адреса у локальной переменной (&foo)
2) указателю можно присвоить целое число и ничто нигде не руганется

в коде случайно прошла замена вот такого:
void foo(error* err) {
   *err = SUCCESS;
}

void bar() {
    error err = SUCCESS;
    foo(&err);
}

на такое:
void foo(error* err) {
   *err = SUCCESS;
}

void bar() {
    error* err = SUCCESS;
    foo(err);
}

Ну и собственно всё. Ошибочный код замечательно прошел все тесты (то есть тестирование не спасло, ошибка вылезла только через 30 дней после рокового комитта). Врукопашную найти ошибку не вышло - искали 50 часов, не нашли, только примерно локализовали.

Удалось справиться только посредством сторонней тулзы для статического анализа кода (PVS Studio).

Такой путь появления ошибки в Обероне просто не возможен!

То есть чтобы компенсировать кривость языка Сишникам пришлось написать дико сложную тулзу статической проверки кода - вот она сложность порождающая еще бОльшую сложность на ровном месте (и позволяющая, между прочим, заработать на этих самых тулзах, чем народ и занимается)!

Примечательно также, что та контора по результатам (с помощью тулзы ошибку удалось найти и устранить за час) приобретать эту тулзу для анализа кода... отказалась! Ибо у них за все эти 50 часов поиска ошибки заплатил заказчик, так что с точки зрения бизнеса - всё норм. А тулзу покупать пришлось бы из своего кармана.

Вот такой он, современный мейнстрим в embedded разработке.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #1 : Январь 14, 2014, 08:23:03 pm »
Замечу, что из за фигурных скобочек таких потерь времени, на моей памяти, не наблюдалось ни разу. А вот борьба с указателями у новичков и не только, в сишном (обычно именно в сишном, а не плюсовом) проекте наблюдается регулярно. В частности неоднократно видел как где-то заводится указатель, а затем сразу используется (разименовывание) явно либо не явно. Еще больше радости когда указатели двойные.
Y = λf.(λx.f (x x)) (λx.f (x x))

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #2 : Январь 14, 2014, 09:58:56 pm »
Cпасибо, посмеялся.

Правда, нормальный компилятор(gcc, clang) не будет ругаться при присваивании указателю не любого числа, а только 0, чем, очевидно, SUCCES и являлась. Взять, что ли, за правило, что SUCCES не ноль?

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #3 : Январь 14, 2014, 10:16:02 pm »
Cпасибо, посмеялся.

Правда, нормальный компилятор(gcc, clang) не будет ругаться при присваивании указателю не любого числа, а только 0, чем, очевидно, SUCCES и являлась. Взять, что ли, за правило, что SUCCES не ноль?

Ну, во-первых правило (в случае С++) простое - не пользоваться голыми указателями вообще. А в данной задаче указатели были вообще не нужны - ведь есть ссылки.

Во-вторых тут есть отличие у С++ и Си. Берем код:
void main()
{
    int* ptr = 0;
    ptr = 2;
}

На первую строчку оно в любом случае не ругается. А вот на вторую...
Берем gcc. В случае Си мы максимум получим warning. Такое языком разрешено. А вот в случае С++ будет error, то есть ошибка компиляции, ибо язык явным образом подобное ЗАПРЕЩАЕТ.

Соответственно вот сишный варнинг:
ptr.c:4:9: warning: assignment makes pointer from integer without a cast [enabled by default]А вот плюсовый еррор:
ptr.cpp:4:9: error: invalid conversion from 'int' to 'int*' [-fpermissive]
Так что я солидарен со Страуструпом - оставаться в embedded (да вообще везде) на Си нет ни одной причины, если там есть вменяемый компилятор С++.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #4 : Январь 14, 2014, 10:30:51 pm »
Да, а в случае C++ если в них использовать нормальные, плюсовые enum'ы (для того же SUCCESS), то опять таки проблем не было бы.

http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations
Y = λf.(λx.f (x x)) (λx.f (x x))

Peter Almazov

  • Sr. Member
  • ****
  • Сообщений: 482
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #5 : Январь 15, 2014, 05:11:09 am »
То есть чтобы компенсировать кривость языка Сишникам пришлось написать дико сложную тулзу статической проверки кода - вот она сложность порождающая еще бОльшую сложность на ровном месте (и позволяющая, между прочим, заработать на этих самых тулзах, чем народ и занимается)!
Упрек к Си, по-моему, несправедливый.
Где тут изначальная сложность со стороны отцов-основателей. Что они могли в данном случае сделать по-другому? Изобрести сразу C++?
Типа, это и есть простота.

Wlad

  • Jr. Member
  • **
  • Сообщений: 91
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #6 : Январь 15, 2014, 08:40:56 am »
В чём претензии к Си(++) ??????????????????????????????????????
Всё ко всему можно присвоить?
ТАК ОН ИМЕННО ДЛЯ ЭТОГО И ДЕЛАЛСЯ! :)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #7 : Январь 15, 2014, 08:53:30 am »
В чём претензии к Си(++) ??????????????????????????????????????
Всё ко всему можно присвоить?
ТАК ОН ИМЕННО ДЛЯ ЭТОГО И ДЕЛАЛСЯ! :)
Ну, в С++ таки не все всему можно присвоить без явного указания компилятору, что ты знаешь что делаешь. Ибо типизация (в основном) строгая, в отличие от Си.

Кстати, многие сишники именно за это (значительно более строгую типизацию) С++ и не любят - лишняя писанина, говорят. Компилятор нам не доверяет, говорят. А уж современный С++ им совсем должен быть отвратен :-)
Y = λf.(λx.f (x x)) (λx.f (x x))

Wlad

  • Jr. Member
  • **
  • Сообщений: 91
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #8 : Январь 15, 2014, 09:02:19 am »
Но мне больше всего понравилось именно само объявление функции:

void foo(error* err) ...
У него - глубочайший сакральный смысл! В смысле что и для чего пользуем... :)
(Конечно же, может быть автор сообщения на хабре просто "проиллюстрировал"...)

Wlad

  • Jr. Member
  • **
  • Сообщений: 91
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #9 : Январь 15, 2014, 09:05:44 am »
Ну, в С++ таки не все всему можно присвоить без явного указания компилятору, что ты знаешь что делаешь. Ибо типизация (в основном) строгая, в отличие от Си.

Говорят - да...

Кстати, многие сишники именно за это (значительно более строгую типизацию) С++ и не любят - лишняя писанина, говорят. Компилятор нам не доверяет, говорят. А уж современный С++ им совсем должен быть отвратен :-)

Кстати, правильно говорят...
Си хорош в своей нише.
Даже более скажу, пока лучше - ничего не придумали для системного и низкоуровневого программирования.
А там - просто как воздух необходим всяческий произвол и "извращения" с минимальными усилиями. :)

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #10 : Январь 15, 2014, 09:24:32 am »
Ну, во-первых правило (в случае С++)
...
Во-вторых тут есть отличие у С++ и Си.
...
Так что я солидарен со Страуструпом - оставаться в embedded (да вообще везде) на Си нет ни одной причины, если там есть вменяемый компилятор С++.
Ну я-то как раз использую Си, но стараюсь писать так, чтобы можно было собрать и как С++. И, кстати, поэтому могу сказать, что последнее утверждение не совсем верно. К примеру gcc выдаёт чуть более компактный и более быстрый код, если его собирать как Си проект. Странно, но факт, а уж g++ компилятор вменяемый.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #11 : Январь 15, 2014, 09:29:31 am »
Но мне больше всего понравилось именно само объявление функции:

void foo(error* err) ...
У него - глубочайший сакральный смысл! В смысле что и для чего пользуем... :)
(Конечно же, может быть автор сообщения на хабре просто "проиллюстрировал"...)

Ненене, в моем сообщение не было копипасты (ни кода, ни текста) из сообщения автора на хабре. Это чисто мой код, как я понял их проблему.

Код я предельно сократил.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #12 : Январь 15, 2014, 09:31:46 am »
Ну, во-первых правило (в случае С++)
...
Во-вторых тут есть отличие у С++ и Си.
...
Так что я солидарен со Страуструпом - оставаться в embedded (да вообще везде) на Си нет ни одной причины, если там есть вменяемый компилятор С++.
Ну я-то как раз использую Си, но стараюсь писать так, чтобы можно было собрать и как С++. И, кстати, поэтому могу сказать, что последнее утверждение не совсем верно. К примеру gcc выдаёт чуть более компактный и более быстрый код, если его собирать как Си проект. Странно, но факт, а уж g++ компилятор вменяемый.

Странно. Пример можно? А если отключить исключения и выкинуть рантайм (это в опциях компилятора есть)?
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #13 : Январь 15, 2014, 09:42:58 am »
Кстати, правильно говорят...
Си хорош в своей нише.
Даже более скажу, пока лучше - ничего не придумали для системного и низкоуровневого программирования.
Я бы таки уточнил - железоориентированное программирование (то есть близкое к железу). Оно при этом может быть вполне себе высокоуровневым и прикладным, а не системным.

А там - просто как воздух необходим всяческий произвол и "извращения" с минимальными усилиями. :)
Нужны. Но нужно иметь возможность извращения эти огородить, кроме того, синтаксические извращения как раз не нужны :-)

По поводу того, что лучше не придумали - я пока не знаю. Скажем тот же Astrobe вроде бы вполне успешно решает задачи, народ не стенает и не мучается, хотя там Оберон. Ексельсиоровцы вроде бы вполне оный Ексельсиор на модуле-2 написали, и тоже без особых страданий. А это же юникс. Ну и так далее.
Y = λf.(λx.f (x x)) (λx.f (x x))

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Безопасность и Си.
« Ответ #14 : Январь 15, 2014, 10:48:01 am »
Странно. Пример можно? А если отключить исключения и выкинуть рантайм (это в опциях компилятора есть)?
Отключить рантайм я не могу, не поработав над проектом дополнительно, что мне разумеется не нужно. Как отключить исключения - не знаю, нас ведь уверяют, что в С++ не платят за то, что не используют. Разумеется, в проекте исключений нет. Сам проект, увы, привести не могу. Вот что показывают результаты эксперимента:
gcc - 4.4.3, strip 2.20.1, valgrind - 3.6.0
Язык    Размер    Callgrind refs
Си1533201,489,518,733
С++1902521,532,850,808
Проект для ПК, но теоретически соотношение может соблюдаться и для специализированных версий gcc.