Re[11]: Что толку в Ада если Ариан 5 все равно упал
От: Кодёнок  
Дата: 05.07.05 11:27
Оценка: 1 (1) :))
AVC>Что-то здесь не так...

Ты не один это чувствуешь
Re[4]: Что толку в Ада если Ариан 5 все равно упал
От: Трурль  
Дата: 05.07.05 11:32
Оценка: 1 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:

AVC>>Практически вся работа с памятью в Си/Си++ ведется опасными средствами.


PD>Именно благодаря этому код на C/C++ столь эффективен.


Опыт общения с различными программами заставляет меня усомниться в истинности данного высказывания.
Re[10]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 12:27
Оценка:
Здравствуйте, Кодт, Вы писали:

AVC>>А что касается "совместимости с хреновыми предшественниками", то разве только MS этим занимается?

AVC>>Да весь Си++ на этом выстроен, как Петербург на болоте!

К>Как петербуржец и сиплюсплюсник, я должен обидеться или возгордиться?


Как петербуржец — несомненно возгордиться!
А вот как сиплюсплюсник... (задумчиво) это как совесть подсказывает...

К>Насчёт чудесатости: необходимо и достаточно, чтобы

К>1) некто единожды написал библиотеку строгих типов с требуемой функциональностью
К>2) остальные пользовались именно ею, а не мешали в кучу с голыми сишными типами
К>STL + boost, большей частью, уже выполнили п.1. Осталось дело за малым — за п.2...

Если бы разумные правила были заложены в сам язык, а не только в библиотеки, то пункт 2 выполнялся бы автоматически.

К>А тут уже дело привычки: если кому-то проще накопипастить

К>
К>if(x==0) a0 = a0+1;
К>if(x==1) a1 = a1+1;
К>...
К>if(x==99) a99 = a99+1;
К>// вместо
К>if(x>=0&&x<=99) ++a[x];
К>

К>(пример, адаптированный из книги "Жемчужины программирования" — только там было на Коболе)
К>то это лечится электричеством.

Запоминающийся пример! (И хорошая книга.)
Ну вот, я видел такое раньше только на Коболе, а теперь — и на Си. Ну никакой разницы!

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[10]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 12:58
Оценка: :)
Здравствуйте, CrystaX, Вы писали:

CX>Алексей, давай я твои примеры сейчас переделаю немного, ок?


(подозрительно) Ну, OK.

AVC>>А есть способ создать указатель на массив в динамической памяти, не прибегая к явному приведению типа?

AVC>>
AVC>>int (*p)[10] = ((*)[10]) new int[10]; // радует также возможность употребить одну и ту же константу трижды :) 
AVC>>


CX>Например, так:

CX>
CX>vector<int> *p = new vector<int>(10);
CX>// Конечно же, удалить тоже надо не забыть. А лучше всего воспользоваться смарт-пойнтером. Например, так:
CX>auto_ptr<vector<int> > p(new vector<int>(10));
CX>// Вот тут даже удалять не надо. Но остается проблема с семантикой передачи владения у auto_ptr.
CX>// Хорошо, сделаем так:
CX>boost::shared_ptr<vector<int> > p(new vector<int>(10));
CX>// Тут уже можно копировать сколько угодно и куда хочешь. Но как же быть, если хочется избежать оверхеда
CX>// от дополнительного выделения памяти для счетчика? Например, используя linked_ptr от Максима Егорушкина
CX>// или другие, обеспечивающие иное поведение. В общем, на выбор пожаловаться нельзя.
CX>


AVC>>Посмотрим, решает ли все проблемы введение указателя на массив.

CX>[skipped]

CX>А теперь так:

CX>
CX>template <typename Array>
CX>void foo(Array &p)
CX>{
CX>}

CX>void test_foo(size_t size)
CX>{
CX>    vector<int> a(10);
CX>    auto_ptr<vector<int> > p(new vector<int>(size));
CX>    foo(a);  // Все работает
CX>    foo(*p); // И здесь тоже!
CX>}
CX>


+1
Как просто-то!
Где нам с Обероном чай пить...

AVC>>Ай, получил сообщение компилятора (GNU C++):

AVC>>

AVC>>Internal compiler error 243.

AVC>>К чему бы это? Наверное, к дождю. Уже голова болит от того, что даже такая мелочь здесь проблема.
AVC>>Может, какому-нибудь компилятору Си++ (например, Comeau C++) повезло бы здесь больше? Но выяснить это уже нет сил.

CX>Интересно, а какая версия GCC? Небось старичка используешь? Потому как у меня GCC 3.4.2 отругался на этот код как положено. Ты используешь run-time value в объявлении указателя на массив. Нельзя. Должна быть compile-time. Посмотри мой код — там эти проблемы решены, причем без всяких усилий с моей стороны — я просто использовал стандартную библиотеку.


Ты прав.
На работе у меня 3.4.2, как у тебя (но, увы, нет http ), а вот дома — пока еще старенький 2.95.
Ошибку я, конечно, сделал нарочно, из вредности.
Чтобы показать, что то твое решение еще было не вполне адекватное.
Что же касается стандартной библиотеки, то там есть свои подводные камни.
Я недавно приводил пример, когда нам потребовался трехмерный массив заранее неизвестных измерений для проведения небольшого эксперимента.
На Обероне — дело одной минуты, а вот с векторами провозились дольше.
Надо было использовать не reserve(), а resize().

AVC>>А что касается "совместимости с хреновыми предшественниками", то разве только MS этим занимается?

AVC>>Да весь Си++ на этом выстроен, как Петербург на болоте!

CX>Ты путаешь две вещи:

CX>1. Совместимость с C кодом (практически все компиляторы стараются этому соответствовать)
CX>2. Совместимость с хреновыми предшественниками (более ранними и более плохими версиями компиляторов)

(важно) Я не путаю. Я обобщаю.
P.S. Схожу куплю себе тортик — как-никак, юбилейный пост!

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[11]: Что толку в Ада если Ариан 5 все равно упал
От: CrystaX Россия https://crystax.me/
Дата: 05.07.05 13:15
Оценка:
Здравствуйте, AVC, Вы писали:

AVC>Здравствуйте, CrystaX, Вы писали:


CX>>Алексей, давай я твои примеры сейчас переделаю немного, ок?


AVC>(подозрительно) Ну, OK.




AVC>Ты прав.

AVC>На работе у меня 3.4.2, как у тебя (но, увы, нет http ), а вот дома — пока еще старенький 2.95.
AVC>Ошибку я, конечно, сделал нарочно, из вредности.
AVC>Чтобы показать, что то твое решение еще было не вполне адекватное.

На самом деле то было вовсе не решение. Я просто изменил сигнатуру функцию и предложил тебе посмотреть, что в таком случае скажет компилятор. Решение — это использовать стандартную библиотеку.

AVC>Что же касается стандартной библиотеки, то там есть свои подводные камни.

AVC>Я недавно приводил пример, когда нам потребовался трехмерный массив заранее неизвестных измерений для проведения небольшого эксперимента.
AVC>На Обероне — дело одной минуты, а вот с векторами провозились дольше.

Да как тебе сказать... Мне здесь ничего сложного не видится. На векторах — тоже дело одной минуты. Ну или если хочется обязательно массивы с ровным краем (а не с резаным, как может быть с векторами), то велосипед пишется за 2 минуты. Или используется готовый. Тут, скорее всего, не со стандартной библиотекой проблема, а с привычками.

AVC>Надо было использовать не reserve(), а resize().


Ну вот видишь! Все дело в чтении документации.

CX>>Ты путаешь две вещи:

CX>>1. Совместимость с C кодом (практически все компиляторы стараются этому соответствовать)
CX>>2. Совместимость с хреновыми предшественниками (более ранними и более плохими версиями компиляторов)

AVC>(важно) Я не путаю. Я обобщаю.

AVC>P.S. Схожу куплю себе тортик — как-никак, юбилейный пост!

Эээ... А что в нем юбилейного? Не заметил.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[4]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 13:44
Оценка: 3 (1) -2
Здравствуйте, Pavel Dvorkin, Вы писали:

AVC>>Дело не только в выходе за пределы массива.

AVC>>Практически вся работа с памятью в Си/Си++ ведется опасными средствами.

PD>Именно благодаря этому код на C/C++ столь эффективен.


Ненамного эффективнее Оберона.
Если отключить run-time проверки (хотя они в Обероне реализованы весьма эффективно — так спроектирован язык), то преимущества вообще нет.
Но я противник удаления проверок из кода.
А правда заключается в том, что Страуструп (ИМХО на сегодня , может измениться в будущем) изначально отказался от надежности ради (достаточно эфемерной) эффективности кода, а теперь это необходимое свойство пытается протащить "в окно" с помощью шаблонов, чрезмерно усложняя язык. Своих ошибок он признавать не хочет, благодаря чему выглядит в глазах наивной общественности "Страшилой мудрым". А ведь весь секрет в том, что в голове солома.

AVC>>А что касается конкретной Вашей рекомендации (ASSERT), то ничего против нее не имею.

AVC>>Но только (по крайней мере, в чистом виде) не выручит она Вас в случае с массивом. Ведь массив в Си/Си++ в качестве параметра синтаксически неотличим от указателя (т.е. и есть указатель). Чем же поможет Вам ASSERT применительно к указателю, просто указателю?

PD>К просто указателю — ничем. Но если он (я это знаю) показывает на область памяти, которую я рассматриваю как массив, то он поможет, так как размер мне известен, а указатель всегда индексируется. Проверьте индекс, и все дела.

PD>Если же указатель показывает не на массив, то индексы здесь ни при чем.

Я не понял. Откуда Вам известен размер массива?
Или у Вас в программе больше одного массива не водится?

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[5]: Что толку в Ада если Ариан 5 все равно упал
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 05.07.05 14:47
Оценка: +2
Здравствуйте, AVC, Вы писали:

AVC>>>Дело не только в выходе за пределы массива.

AVC>>>Практически вся работа с памятью в Си/Си++ ведется опасными средствами.
PD>>Именно благодаря этому код на C/C++ столь эффективен.
AVC>Ненамного эффективнее Оберона.
AVC>Если отключить run-time проверки (хотя они в Обероне реализованы весьма эффективно — так спроектирован язык), то преимущества вообще нет.
AVC>Но я противник удаления проверок из кода.
AVC>А правда заключается в том, что Страуструп (ИМХО на сегодня , может измениться в будущем) изначально отказался от надежности ради (достаточно эфемерной) эффективности кода, а теперь это необходимое свойство пытается протащить "в окно" с помощью шаблонов, чрезмерно усложняя язык. Своих ошибок он признавать не хочет, благодаря чему выглядит в глазах наивной общественности "Страшилой мудрым". А ведь весь секрет в том, что в голове солома.

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

Это как раз и есть усложнение языка и усложнение жизни разработчикам компиляторов. Так что, тут Страуструп прав — язык должен предоставлять достаточные средства для разработки библиотек, а не пытаться решать "всё, что можно решить". Такие проблемы разумно пребросить разработчикам прикладных библиотек.

Потом, нередко пользуются таким трюком: помещают в -1-й элемент массива некоторую служебную информацию (например, так поступили в MFC::CString). Ну и наверни сюда ещё проверку на выход за границу, что получится? Хак?
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[6]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 16:00
Оценка: :)
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>Здравствуйте, AVC, Вы писали:


AVC>>>>Дело не только в выходе за пределы массива.

AVC>>>>Практически вся работа с памятью в Си/Си++ ведется опасными средствами.
PD>>>Именно благодаря этому код на C/C++ столь эффективен.
AVC>>Ненамного эффективнее Оберона.
AVC>>Если отключить run-time проверки (хотя они в Обероне реализованы весьма эффективно — так спроектирован язык), то преимущества вообще нет.
AVC>>Но я противник удаления проверок из кода.
AVC>>А правда заключается в том, что Страуструп (ИМХО на сегодня , может измениться в будущем) изначально отказался от надежности ради (достаточно эфемерной) эффективности кода, а теперь это необходимое свойство пытается протащить "в окно" с помощью шаблонов, чрезмерно усложняя язык. Своих ошибок он признавать не хочет, благодаря чему выглядит в глазах наивной общественности "Страшилой мудрым". А ведь весь секрет в том, что в голове солома.

ГВ>Да нет, ни к чему вводить такие проверки в качестве обязательного средства языка. Сразу же возникает вопрос: какие ещё проверки нужно ввести кроме контроля выхода за границы массива? Чем таким особенным массивы выделяются из класса наборов?


Массив находится в памяти. Когда мы адресуемся к элементу массива, как правило мы обращаемся к нему с заранее неизвестныи (вычисляемым) индексом. Да и размерность массива зачастую неизвестна на этапе компиляции. Чтобы программа по ошибке не испортила память вне массива, надо вставить проверку индекса.
Для этого компилятор должен знать, откуда извлечь информацию о массиве. Компилятор Оберона это знает, а компилятор Си++ — нет, потому что массив в Си++ передается как указатель, от которого ничего не добьешься — молчит как партизан.
Кроме индекса массива, в Обероне проверяются на NIL указатели и процедурные переменные. (Если они имеют значение, отличное от NIL, то их валидность гарантируется. В том числе — сборщиком мусора.)
Еще иногда требуется проверка динамического типа переменной. Для этого в Обероне достаточно одного сравнения.
Вот, пожалуй, и все необходимые проверки в Обероне. Можете видеть сами — все они связаны с безопасностью типов и требуют не более одного-двух (для индекса массива) сравнений.
Этого достаточно, чтобы компилятор гарантировал обращение с переменными только в соответствии с их типом (type safety).
Для исключения ошибок в вычислениях иногда желательны проверки на переполнение и т.п. В этом Оберон не отличается от других языков. Оберон позволяет как использовать, так и отключать подобные проверки. (Лично я против такого отключения.)

ГВ>Это как раз и есть усложнение языка и усложнение жизни разработчикам компиляторов. Так что, тут Страуструп прав — язык должен предоставлять достаточные средства для разработки библиотек, а не пытаться решать "всё, что можно решить". Такие проблемы разумно пребросить разработчикам прикладных библиотек.


Может быть, тогда разумно иметь два языка: для создателей библиотек и всех прочих?

ГВ>Потом, нередко пользуются таким трюком: помещают в -1-й элемент массива некоторую служебную информацию (например, так поступили в MFC::CString). Ну и наверни сюда ещё проверку на выход за границу, что получится? Хак?


Еще скорее — кряк.
Рассмотрим пример.
Создадим в динамической памяти массив объектов, для которых определен деструктор.
Чтобы обеспечить отработку деструкторов при удалении массива, Си++ сохранит прямо перед массивом число элементов в массиве.
Тем самым поддерживается оператор
delete [] p;

Кажется, все хорошо. Но ведь Си++ не обеспечивает type safety. Следовательно, я могу по ошибке присвоить какое-нибудь значение элементу p[i], где i, например, может быть равным -1.
Последствия непредсказуемы.
Что это — хак, кряк? Или хрюк? Применительно к Страуструпу — скорее последнее.
(Ничего не могу с собой поделать. Я его очень не люблю. Я вообще не люблю жуликов. Но я постараюсь освоить современный Си++; может быть, пойму, почему Си++ — это хорошо. И буду ходить по улицам и распевать "Харе, Кришна!")

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[7]: Что толку в Ада если Ариан 5 все равно упал
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 05.07.05 16:30
Оценка: -1
Здравствуйте, AVC, Вы писали:

AVC>>>А правда заключается в том, что Страуструп (ИМХО на сегодня , может измениться в будущем) изначально отказался от надежности ради (достаточно эфемерной) эффективности кода, а теперь это необходимое свойство пытается протащить "в окно" с помощью шаблонов, чрезмерно усложняя язык. Своих ошибок он признавать не хочет, благодаря чему выглядит в глазах наивной общественности "Страшилой мудрым". А ведь весь секрет в том, что в голове солома.


ГВ>>Да нет, ни к чему вводить такие проверки в качестве обязательного средства языка. Сразу же возникает вопрос: какие ещё проверки нужно ввести кроме контроля выхода за границы массива? Чем таким особенным массивы выделяются из класса наборов?


AVC>Массив находится в памяти. Когда мы адресуемся к элементу массива, как правило мы обращаемся к нему с заранее неизвестныи (вычисляемым) индексом. Да и размерность массива зачастую неизвестна на этапе компиляции. Чтобы программа по ошибке не испортила память вне массива, надо вставить проверку индекса.


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

AVC>Для этого компилятор должен знать, откуда извлечь информацию о массиве. Компилятор Оберона это знает, а компилятор Си++ — нет, потому что массив в Си++ передается как указатель, от которого ничего не добьешься — молчит как партизан.


Это наследие C и, кроме того, остаётся открытым вопрос: как конкретно должен быть реализован массив? std::vector<> — то частное решение, хоть и стандартизированное.

AVC>Кроме индекса массива, в Обероне проверяются на NIL указатели и процедурные переменные. (Если они имеют значение, отличное от NIL, то их валидность гарантируется. В том числе — сборщиком мусора.)


Опять таки, проверки на NULL (NIL) по месту вызова нужны не всегда. Точно так же, как и с массивами. Зачастую гораздо проще проверить валидность структур перед началом выполнения алгоритма, чем проверять их при каждом использовании.

AVC>Еще иногда требуется проверка динамического типа переменной. Для этого в Обероне достаточно одного сравнения.

А это вообще часто называется ошибкой проектирования.

AVC>Вот, пожалуй, и все необходимые проверки в Обероне. Можете видеть сами — все они связаны с безопасностью типов и требуют не более одного-двух (для индекса массива) сравнений.

Угу, но каждый раз...

AVC>Этого достаточно, чтобы компилятор гарантировал обращение с переменными только в соответствии с их типом (type safety).

AVC>Для исключения ошибок в вычислениях иногда желательны проверки на переполнение и т.п. В этом Оберон не отличается от других языков. Оберон позволяет как использовать, так и отключать подобные проверки. (Лично я против такого отключения.)
В отладочных версиях такие проверки полезны, спору нет. В не-отладочных такие проверки очень круто сажают производительность, особенно при большом количестве разыменований.

ГВ>>Это как раз и есть усложнение языка и усложнение жизни разработчикам компиляторов. Так что, тут Страуструп прав — язык должен предоставлять достаточные средства для разработки библиотек, а не пытаться решать "всё, что можно решить". Такие проблемы разумно пребросить разработчикам прикладных библиотек.


AVC>Может быть, тогда разумно иметь два языка: для создателей библиотек и всех прочих?

Нет. Это есть очень большая ошибка, потому что комбинаторные способности языков вступят в конфликт друг с другом. У нас и так проблем с импедансом C++ — SQL, C++ — xxxScript и т.п. хватает.

ГВ>>Потом, нередко пользуются таким трюком: помещают в -1-й элемент массива некоторую служебную информацию (например, так поступили в MFC::CString). Ну и наверни сюда ещё проверку на выход за границу, что получится? Хак?


AVC>Еще скорее — кряк.

AVC>Рассмотрим пример.
AVC>Создадим в динамической памяти массив объектов, для которых определен деструктор.
AVC>Чтобы обеспечить отработку деструкторов при удалении массива, Си++ сохранит прямо перед массивом число элементов в массиве.
AVC>Тем самым поддерживается оператор
AVC>
AVC>delete [] p;
AVC>

AVC>Кажется, все хорошо. Но ведь Си++ не обеспечивает type safety. Следовательно, я могу по ошибке присвоить какое-нибудь значение элементу p[i], где i, например, может быть равным -1.

Средствами C++ можно обойти type safety. Разумность такого решения — отдельный вопрос. Если голова на плечах есть — всмё будет в порядке, если с этим проблема, то runtime проверками дела не поправишь. Приведённый пример с NASA свидетельствует, скорее, не о бенефитах типобезопасности, а о том, что всем в NASA было настолько страшно взять ответственность на себя, что спихнули всё на "неправильную" фичу языка. Т.е., проблема не в языке, а в головах.

AVC>Последствия непредсказуемы.


После любого неправильного использования алгоритма последствия непредсказуемы. Ну... пользуйтесь правильными идиомами и т.п.

AVC>Что это — хак, кряк? Или хрюк? Применительно к Страуструпу — скорее последнее.

AVC>(Ничего не могу с собой поделать. Я его очень не люблю. Я вообще не люблю жуликов. Но я постараюсь освоить современный Си++; может быть, пойму, почему Си++ — это хорошо. И буду ходить по улицам и распевать "Харе, Кришна!")
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[7]: Что толку в Ада если Ариан 5 все равно упал
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.07.05 16:36
Оценка: +1
Здравствуйте, AVC, Вы писали:

AVC>Что это — хак, кряк? Или хрюк? Применительно к Страуструпу — скорее последнее.

AVC>(Ничего не могу с собой поделать. Я его очень не люблю. Я вообще не люблю жуликов.

Ребята, давайте Страуструпа оставим в покое. Он сделал то, что сделал. А мы можем либо пользоваться результатами его труда, либо нет. Но я уверен, что разработок масштаба достижений Страуструпа (язык программирования которым пользуются уже 20 лет и пару книг-бестселлеров) никто на данном форуме не достиг и, имхо, далеко не всем суждено достигнуть. Так что "Don't shot pianist...".
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[7]: Что толку в Ада если Ариан 5 все равно упал
От: Кодт Россия  
Дата: 05.07.05 17:13
Оценка: +1 :))
Здравствуйте, AVC, Вы писали:

AVC>Массив находится в памяти. Когда мы адресуемся к элементу массива, как правило мы обращаемся к нему с заранее неизвестныи (вычисляемым) индексом. Да и размерность массива зачастую неизвестна на этапе компиляции. Чтобы программа по ошибке не испортила память вне массива, надо вставить проверку индекса.

AVC>Для этого компилятор должен знать, откуда извлечь информацию о массиве. Компилятор Оберона это знает, а компилятор Си++ — нет, потому что массив в Си++ передается как указатель, от которого ничего не добьешься — молчит как партизан.

Это не совсем так. В точке объявления массива компилятор знает о его размере. Беда в другом: эту compile-time информацию слишком легко потерять (выполнив кастинг вверх).
Компилятор не по своей инициативе теряет её, а молча позволяет сделать это программисту. И это, на самом деле, и есть дурное наследие Си.

Вот пример
typedef int Data;

void foo(void* p) { Data* pData = (Data*)p; ..... } // мы подозреваем, что это должна была быть Data
void bar(Data* p) { Data (&rArray)[123] = *(Data(*)[123])p; ..... } // мы подозреваем, что это массив из 123 элементов
void buz(void* p) { Data (&rArray)[123] = *(Data(*)[123])p; ..... } // мы такие самоуверенные


template<class T>
class array_ref
{
public:
  template<int N> array_ref(T(&plain_old_array)[N]);
  // и другие полезные сигнатуры
  array_ref(std::vector<T> vec);
  template<int N> array_rev(boost::array<T,N> arr);
  .....
};


void good(array_ref<Data> arr) { ..... } // мы не подозреваем, а знаем; информация о размере переехала в run-time.

int main()
{
  Data arr[123];

  foo(&arr[7]); // потеря информации о типе
  bar(arr);     // потеря информации о размере массива (фактически, потеря информации о типе: из Data(&)[N] получили Data*)
  buz(arr);     // потеря вообще всего что возможно

  good(arr); // а ведь можно было и по-человечески, договориться...

  // а если писать вот так:
  boost::array<Data,123> brr;
  // то за голые вызовы foo,bar,buz нам ещё и в лоб дадут.
  good(brr);
}


AVC>Кроме индекса массива, в Обероне проверяются на NIL указатели и процедурные переменные. (Если они имеют значение, отличное от NIL, то их валидность гарантируется. В том числе — сборщиком мусора.)


С++ экономит (большей частью, на спичках): оставляет инициализацию ПОДданных на совести их хозяев.
Зато это позволяет работать с файлмаппингами и большими массивами без дополнительного "прогревочного заезда".

AVC>Еще иногда требуется проверка динамического типа переменной. Для этого в Обероне достаточно одного сравнения.


Если просто сравнить type_info — то и в С++ (правда, не для всех типов, а только для полиморфных классов или обёрток наподобие VARIANT) это тоже занимает одно сравнение.
А если проверять в рантайме принадлежность некоему суперклассу — то я сомневаюсь, что это делается за O(1).

AVC>Вот, пожалуй, и все необходимые проверки в Обероне. Можете видеть сами — все они связаны с безопасностью типов и требуют не более одного-двух (для индекса массива) сравнений.

AVC>Этого достаточно, чтобы компилятор гарантировал обращение с переменными только в соответствии с их типом (type safety).
AVC>Для исключения ошибок в вычислениях иногда желательны проверки на переполнение и т.п. В этом Оберон не отличается от других языков. Оберон позволяет как использовать, так и отключать подобные проверки. (Лично я против такого отключения.)

ГВ>>Это как раз и есть усложнение языка и усложнение жизни разработчикам компиляторов. Так что, тут Страуструп прав — язык должен предоставлять достаточные средства для разработки библиотек, а не пытаться решать "всё, что можно решить". Такие проблемы разумно пребросить разработчикам прикладных библиотек.


AVC>Может быть, тогда разумно иметь два языка: для создателей библиотек и всех прочих?


Ха! Тогда любитель легаси-кодирования просто заявит, что он пишет "библиотеку" и продолжит своё чёрное дело

ГВ>>Потом, нередко пользуются таким трюком: помещают в -1-й элемент массива некоторую служебную информацию (например, так поступили в MFC::CString). Ну и наверни сюда ещё проверку на выход за границу, что получится? Хак?


AVC>Еще скорее — кряк.


Это не хак и не кряк, а непонимание того, как устроен CString.
У него нет "минус-первого" элемента массива (хотя бы потому, что элементы массива — это символы — CHAR/WCHAR, а служебная информация там явно не однобайтная).

Схематично,
class CString
{
  struct Header { ..... };

  // в одном блоке памяти размещены встык некий заголовок и массив символов
  inline Header* header() { return (Header*)block(); }
  inline TCHAR* data() { return (TCHAR*)(header()+1); }

  TCHAR* m_data; // но из некоторых коварных соображений мы храним в объекте указатель не на начало блока, а на точку, где начинается строка
  inline void* block() { return (Header*)m_data-1; }
  inline void setblock(void* blk) { m_data = (TCHAR*)((Header*)blk+1); }

public:
  .....
};
STATIC_ASSERT( sizeof(CString) == sizeof(TCHAR*) );

Такое устройство было сделано для того, чтобы можно было передавать CString в эллипсис под видом обычного указателя на строку. Вообще-то, это неопределённое поведение (если вообще не ill-formed), но для известных компиляторов предсказуемое и нормально работающее.

(А потом привыкаешь, и случайно делаешь printf("%s",string("blabla")); вместо printf("%s",string("blabla").c_str()); )

AVC>Рассмотрим пример.

AVC>Что это — хак, кряк? Или хрюк? Применительно к Страуструпу — скорее последнее.

Нет, просто разгильдяйство. Язык С++ позволяет, вслед за С, деградировать информацию о типах. К ней, кстати говоря, можно отнести и информацию о размещении и времени жизни объекта.
int main()
{
  int array[10];
  delete[] array; // нормальный компилятор надаёт по рукам за такое

  int* trick = array; // но его можно обмануть
  delete[] trick;
}

AVC>(Ничего не могу с собой поделать. Я его очень не люблю. Я вообще не люблю жуликов. Но я постараюсь освоить современный Си++; может быть, пойму, почему Си++ — это хорошо. И буду ходить по улицам и распевать "Харе, Кришна!")

С++, как "пиво с утра — не только вредно, но и полезно". А Оберон — только полезно. Половинчатость, понимаешь
Перекуём баги на фичи!
Re[34]: Что толку в Ада если Ариан 5 все равно упал
От: Павел Кузнецов  
Дата: 05.07.05 18:36
Оценка: 6 (1)
AVC,

> CX>Если Вы посмотрите в той же ветке чуть выше, Вы найдете там более упрощенную реализацию. Там нет систем единиц, а есть только разные физические понятия — длина, масса, время. К системам единиц я пришел, будучи подталкиваемым Кодтом.


> Интересно, что тема эта не новая.

> Наткнулся на днях в старой уже книге (1980-х годов) "Языки программирования Ада, Си, Паскаль. Сравнение и оценка" на статью Джехани, где (в разделе о производных типах) он предлагает подход "единиц измерения", впоследствии реализованный в языке Физкал.
> Надо отметить, что к тому времени в языке Ада уже существовала возможность объявления производных типов:
>
> type LENGTH is new FLOAT;
> type AREA is new FLOAT;
> type VOLUME is new FLOAT;
>

> Объявленные производные типы по умолчанию не могут смешиваться между собой.
> Чтобы разрешить корректное смешение типов (например, когда переменная типа VOLUME получается из произведения переменных типов AREA и LENGTH) требуется определить соответствующие операторы.

К сожалению, в отличие от C++, поддержки сколько-нибудь сложных вычислений при таком подходе не выйдет, т.к. в процессе вычислений и L^4 (квадрат площади), и L^5 (площать * объем), и L / T (скорость), и L^2 / T^2 (квадрат скорости), и M * L / T (импульс), и M * L^2 / T^2 (энергия), и M^2 * L^4 / T^4 (квадрат энергии), и т.п. легко получаются...

> Джехани не понравилось, что требуется определять так много вспомогательных операторов, и он предложил другой способ, который и был реализован в языке Физкал.


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

Аде, на мой поверхностный взгляд, вообще, присуще избыточно явное описание происходящего. Например, "Адские" generics мне кажутся сравнительно неудобными и малофункциональными, т.к. требуют явного инстанцирования всех используемых сигнатур.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[8]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 18:40
Оценка:
Здравствуйте, eao197, Вы писали:

AVC>>Что это — хак, кряк? Или хрюк? Применительно к Страуструпу — скорее последнее.

AVC>>(Ничего не могу с собой поделать. Я его очень не люблю. Я вообще не люблю жуликов.

E>Ребята, давайте Страуструпа оставим в покое. Он сделал то, что сделал. А мы можем либо пользоваться результатами его труда, либо нет. Но я уверен, что разработок масштаба достижений Страуструпа (язык программирования которым пользуются уже 20 лет и пару книг-бестселлеров) никто на данном форуме не достиг и, имхо, далеко не всем суждено достигнуть. Так что "Don't shot pianist...".


Евгений, мне жаль, что я огорчил тебя.
Но ведь у каждого своя точка зрения.
Достижения бывают разными. Мне кажется, если у человека нет достижений вроде тех, которыми отличились Герострат или Гитлер, то это хорошо.
Поэтому аргумент о достижениях вообще не убеждает.
Для меня не является аргументом, что кто-то написал бестселлер. Это чисто коммерческий аргумент, применимый не всегда и не во всех обстоятельствах.
Поэтому аргумент о бестселлерах не принимается, по крайней мере — в абстрактном виде.
Я бы принял его во внимание, если бы был книготорговцем.
По поводу самих книг я хочу сказать, что они написаны действительно хорошо, и они гораздо лучше языка, которому они посвящены. Я и не думал отрицать наличие у Страуструпа таланта.
Гораздо хуже обстоит с языком, которым "пользуются уже 20 лет".
Наш мир вообще очень опасен и нестабилен.
Но некоторые люди делают его еще опаснее.
Ты говоришь, что надо оставить в покое Страуструпа. А он оставит меня в покое?
Все в мире взаимосвязано.
Во-первых, неправда, что у нас есть свобода "не пользоваться результатами его труда".
Если ты обыкновенный программист, тебе, вероятно, придется иногда писать на Си++. В случае твоего гордого отказа другой программист "воспользуется результатами его труда", а тебе будет нечем кормить семью.
Разумеется, в тех случаях, когда у меня есть выбор, я не стану пользоваться Си++. (Я так и делаю, и ни разу не ощутил, что мне не хватает каких-либо "фич" Си++. Поэтому я полагаю, что Си++ — сильно раздутый миф. Конечно, я стараюсь внимательно слушать оппонентов, опасаясь собственных заблуждений. При такой собственной пристрастности мне очень важно иметь возможность услышать и другую точку зрения.)
Во-вторых, я никак не могу понять аргументов, что чрезмерно сложный и раздутый язык, не позволяющий даже в отладочном режиме обеспечить контроль типов, является вершиной человеческой мысли и результатом непосильного труда.
Скорее, я склонен видеть в нем результат халтурной работы.
В-третьих, меня действительно очень волнуют вопросы безопасности.
Говорят, что тому, кто любит кобасу, не надо знать, как она делается.
Моя проблема в том, что я "люблю колбасу", но "знаю, как она делается".
На душе у меня действительно неспокойно. Конечно, не только из-за Страуструпа. Но ведь и из-за него тоже.
Поэтому я не люблю Страуструпа и считаю, что имею право высказывать это вслух, а не шептать ночью в подушку.
Мне жаль, что иногда по несдержанности я делаю это в грубой форме. (Все-таки темперамент у меня, увы, бурный. )
Вместе с тем, мне приятно общаться с интересными мне людьми, даже если им Страуструп нравится.
По возможности, я сдерживаюсь и не слишком выпячиваю свое отношение к автору Си++, а больше сосредотачиваюсь на самом языке.
Но иногда меня все-таки "прорывает". Прости дурака.
Мир?

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[9]: Что толку в Ада если Ариан 5 все равно упал
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.07.05 19:16
Оценка:
Здравствуйте, AVC, Вы писали:

AVC>Здравствуйте, eao197, Вы писали:


AVC>>>Что это — хак, кряк? Или хрюк? Применительно к Страуструпу — скорее последнее.

AVC>>>(Ничего не могу с собой поделать. Я его очень не люблю. Я вообще не люблю жуликов.

E>>Ребята, давайте Страуструпа оставим в покое. Он сделал то, что сделал. А мы можем либо пользоваться результатами его труда, либо нет. Но я уверен, что разработок масштаба достижений Страуструпа (язык программирования которым пользуются уже 20 лет и пару книг-бестселлеров) никто на данном форуме не достиг и, имхо, далеко не всем суждено достигнуть. Так что "Don't shot pianist...".


AVC>Но иногда меня все-таки "прорывает". Прости дурака.

AVC>Мир?

Мир, конечно!

Просто, имхо, невежливо неуважительно отзываться о человеке, который тебе вообще ничем ответить не может. Не красиво это.
К тому же я недавно уже наслушался про Страутрупа в другом флэйме, так что это твое высказывание стало "последней каплей" из-за которой меня самого прорвало.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 20:24
Оценка: +1 :)
Здравствуйте, Геннадий Васильев, Вы писали:

AVC>>Массив находится в памяти. Когда мы адресуемся к элементу массива, как правило мы обращаемся к нему с заранее неизвестныи (вычисляемым) индексом. Да и размерность массива зачастую неизвестна на этапе компиляции. Чтобы программа по ошибке не испортила память вне массива, надо вставить проверку индекса.


ГВ>Куда? Массив может быть закопан в глубине абстракции, а проверка индекса выполняться на несколько уровней выше. Ошибка по индексу приведёт к выкидыванию исключения и отказу в работе алгоритма более высокого уровня. Следовательно, проверять индекс нужно до его использования, следовательно, проверять индекс на уровне массива никакой необходимости нет — всё равно он ему "приходит" уже заведомо корректным.


Все-таки подозрительно, что проверка индекса может "привести к исключению", если индекс "приходит уже корректным".
Кроме того, не до конца понятно, как проверять индексы до обращения к элементу массива.
Ведь число становится индексом только в момент обращения к элементу массива.
В некоторых случаях излишние проверки могут устраняться оптимизатором.
Например, в процедуре
PROCEDURE Init(VAR a: ARRAY OF INTEGER);
  VAR i: LONGINT;
BEGIN
  FOR i := 0 TO LEN(a)-1 DO
    a[i] := 0;
  END;
END Init;

проверки вообще необязательны. Код заведомо корректен, т.к. значение i не меняется внутри цикла.

AVC>>Для этого компилятор должен знать, откуда извлечь информацию о массиве. Компилятор Оберона это знает, а компилятор Си++ — нет, потому что массив в Си++ передается как указатель, от которого ничего не добьешься — молчит как партизан.


ГВ>Это наследие C и, кроме того, остаётся открытым вопрос: как конкретно должен быть реализован массив? std::vector<> — то частное решение, хоть и стандартизированное.


Пока не изобретен лучший вариант, меня вполне устраивает виртовское решение.

AVC>>Кроме индекса массива, в Обероне проверяются на NIL указатели и процедурные переменные. (Если они имеют значение, отличное от NIL, то их валидность гарантируется. В том числе — сборщиком мусора.)


ГВ>Опять таки, проверки на NULL (NIL) по месту вызова нужны не всегда. Точно так же, как и с массивами. Зачастую гораздо проще проверить валидность структур перед началом выполнения алгоритма, чем проверять их при каждом использовании.


Существует понятие программирования по контракту. (Мейер)
Главный принцип: не доверяй клиенту (вызывающему коду).

AVC>>Еще иногда требуется проверка динамического типа переменной. Для этого в Обероне достаточно одного сравнения.

ГВ>А это вообще часто называется ошибкой проектирования.

Это смотря как и где этим пользоваться.
В Си++ также есть соответствующие "касты".
В самом первом виртовском Обероне не было присоединенных процедур (=виртуальных функций).
Полиморфизм работал исключительно благодаря динамическому приведению типа.
Наверное, поэтому динамическое приведение типа реализовано так эффективно.
Например (опустив все лишнее):
MODULE Objects;
  TYPE
    Msg        = RECORD END;
    Object     = POINTER TO ObjectDesc;
    ObjectDesc = RECORD
      handle: PROCEDURE(this: Object; VAR msg: Msg);
    END;

    (* ... *)

    Module     = POINTER TO ModuleDesc;
    ModuleDesc = RECORD (ObjectDesc)
      (* ... *)
    END;

  VAR module: Module;

  PROCEDURE HandleModule(this: Object; VAR msg: Msg);
    VAR m: Module;
  BEGIN m := this(Module); (* динамическое приведение типа (конечно, с проверкой) *)
    (* ... *)
  END Handle;

BEGIN NEW(module); module.handle := ModuleHandle;
END Objects.


AVC>>Вот, пожалуй, и все необходимые проверки в Обероне. Можете видеть сами — все они связаны с безопасностью типов и требуют не более одного-двух (для индекса массива) сравнений.

ГВ>Угу, но каждый раз...

Опять-таки оптимизатор может устранить некоторые лишние проверки.

AVC>>Этого достаточно, чтобы компилятор гарантировал обращение с переменными только в соответствии с их типом (type safety).

AVC>>Для исключения ошибок в вычислениях иногда желательны проверки на переполнение и т.п. В этом Оберон не отличается от других языков. Оберон позволяет как использовать, так и отключать подобные проверки. (Лично я против такого отключения.)
ГВ>В отладочных версиях такие проверки полезны, спору нет. В не-отладочных такие проверки очень круто сажают производительность, особенно при большом количестве разыменований.

Измерения производительности этого не подтверждают.

ГВ>Средствами C++ можно обойти type safety. Разумность такого решения — отдельный вопрос. Если голова на плечах есть — всмё будет в порядке, если с этим проблема, то runtime проверками дела не поправишь. Приведённый пример с NASA свидетельствует, скорее, не о бенефитах типобезопасности, а о том, что всем в NASA было настолько страшно взять ответственность на себя, что спихнули всё на "неправильную" фичу языка. Т.е., проблема не в языке, а в головах.


Согласен, что проблема — в головах.
Потому что именно из голов она попадает в языки.
Забавно читать, что "средствами C++ можно обойти type safety".
Где бы найти в Си++ эту самую type safety...

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[9]: Что толку в Ада если Ариан 5 все равно упал
От: Кодт Россия  
Дата: 05.07.05 21:02
Оценка: 2 (2) +3 :))
Здравствуйте, AVC, Вы писали:

ГВ>>Средствами C++ можно обойти type safety. Разумность такого решения — отдельный вопрос. Если голова на плечах есть — всмё будет в порядке, если с этим проблема, то runtime проверками дела не поправишь. Приведённый пример с NASA свидетельствует, скорее, не о бенефитах типобезопасности, а о том, что всем в NASA было настолько страшно взять ответственность на себя, что спихнули всё на "неправильную" фичу языка. Т.е., проблема не в языке, а в головах.


AVC>Согласен, что проблема — в головах.

AVC>Потому что именно из голов она попадает в языки.
AVC>Забавно читать, что "средствами C++ можно обойти type safety".
AVC>Где бы найти в Си++ эту самую type safety...

Скорее, "в С++ можно обрести type safety... если руки дойдут... если эти руки тимлидер не повыдёргивал ещё раньше..."
Перекуём баги на фичи!
Re[10]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 21:03
Оценка:
Здравствуйте, eao197, Вы писали:

AVC>>Но иногда меня все-таки "прорывает". Прости дурака.

AVC>>Мир?

E>Мир, конечно!




E>Просто, имхо, невежливо неуважительно отзываться о человеке, который тебе вообще ничем ответить не может. Не красиво это.


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

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[35]: Что толку в Ада если Ариан 5 все равно упал
От: AVC Россия  
Дата: 05.07.05 21:03
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>К сожалению, в отличие от C++, поддержки сколько-нибудь сложных вычислений при таком подходе не выйдет, т.к. в процессе вычислений и L^4 (квадрат площади), и L^5 (площать * объем), и L / T (скорость), и L^2 / T^2 (квадрат скорости), и M * L / T (импульс), и M * L^2 / T^2 (энергия), и M^2 * L^4 / T^4 (квадрат энергии), и т.п. легко получаются...


Согласен.
Действительно, получается абсурд.
Что-то вроде
VAR a, b, c: LENGTH;
...
  c := a * b;

Здесь простота объявления "производного" типа не соответствует реальности.

>> Джехани не понравилось, что требуется определять так много вспомогательных операторов, и он предложил другой способ, который и был реализован в языке Физкал.


ПК>Хочу подчеркнуть, что это не из категории нравится/не нравится, а из категории осуществимо/неосуществимо, т.к. явное определение всех нужных комбинаций типов, плюс их взаимодействий, нереально.


ПК>Аде, на мой поверхностный взгляд, вообще, присуще избыточно явное описание происходящего. Например, "Адские" generics мне кажутся сравнительно неудобными и малофункциональными, т.к. требуют явного инстанцирования всех используемых сигнатур.


Да, не слишком удобно.
Но, может быть, иногда это имеет смысл?

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[36]: Что толку в Ада если Ариан 5 все равно упал
От: Павел Кузнецов  
Дата: 06.07.05 00:34
Оценка: 1 (1)
AVC,

> Здесь простота объявления "производного" типа не соответствует реальности.


+1

"Simple things simple. Complex things possible." — в данном случае, к сожалению, выполняется только первая часть.

> ПК> Аде, на мой поверхностный взгляд, вообще, присуще избыточно явное описание происходящего. Например, "Адские" generics мне кажутся сравнительно неудобными и малофункциональными, т.к. требуют явного инстанцирования всех используемых сигнатур.


> Да, не слишком удобно.

> Но, может быть, иногда это имеет смысл?

Конечно. Когда разрабатываешь компилятор

Насколько можно верить rationale к спецификации Ada83, в Аде было решено ограничиться явным инстанцированием из-за сложностей компиляции в присутствии неявного:

The requirement that instantiation be explicit greatly simplifies the compilation of program units obtained by generic instantiation.


К сожалению, это лишило (или избавило — в зависимости от отношения) Аду такой библиотеки как STL — по крайней мере так говорил Степанов в одном из интервью. Более того, за многие аспекты нынешних шаблонов C++ следует благодарить (или винить) именно STL: членам комитета настолько понравилась библиотека, что местами они "прогибали" под нее язык, делая возможным полноценное использование STL. В общем, это меня уже совсем в другую сторону понесло...
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: Что толку в Ада если Ариан 5 все равно упал
От: Павел Кузнецов  
Дата: 06.07.05 00:56
Оценка: 1 (1) +3
AVC,

> Массив находится в памяти. Когда мы адресуемся к элементу массива, как правило мы обращаемся к нему с заранее неизвестныи (вычисляемым) индексом. Да и размерность массива зачастую неизвестна на этапе компиляции. Чтобы программа по ошибке не испортила память вне массива, надо вставить проверку индекса.

> Для этого компилятор должен знать, откуда извлечь информацию о массиве. Компилятор Оберона это знает, а компилятор Си++ — нет, потому что массив в Си++ передается как указатель, от которого ничего не добьешься — молчит как партизан.

Отсюда какой должен следовать вывод у человека, которому надежность работы его программ небезразлична? На мой взгляд простой: не передавать массивы в C++ через указатели. Благо, возможностей для этого хоть отбавляй: от std::vector до самописных классов массивов...
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.