Здравствуйте, Сергей Губанов, Вы писали:
WH>> Вот там они и сидят. В принципе они только и нужны для написания библиотек низкого уровня. Короче можешь считать что они спрятаны в нутрь компилятора.
СГ>Если бы да кабы, то в носу бы выросли грибы.
Кто-то здесь учил друг друга хорошим манерам
WH>> Кстати а как на счет ошибок в компиляторе оберона?...
СГ>ЧТО???????????????
А почему бы и нет?
Для С++ пишутся специальные библиотеки тестовых сырцов на все случаи жизни, и скармливаются компилятору. После чего выносится вердикт: "данный компилятор на N% совместим со Стандартом" (столько-то правильных файлов не распознал или породил неправильный код; столько-то заведомо ошибочных скомпилировал и не мяукнул).
Да, С++ — язык сложный, в том числе сложный для компилятора. Поэтому придумать всеохватные тесты — это гиганский труд.
Но существуют ли такие тесты для Оберонов? Кстати, трудоёмкость здесь будет вызвана большим количеством языков в семействе, обладающих к тому же разнородным синтаксисом. Это значит — опять копипаст и доводка напильником...
Похоже, идиома копипаста довольно глубоко засела в язык, что даже сюда добралась.
Здравствуйте, Кодт, Вы писали:
AVC>>В Си++ типизация сильнее, чем в Обероне? AVC>>Это Вы баек о пользе шаблонов в Си++ наслушались? AVC>>А как Вам конструкции вида AVC>>
К>Да, сильнее. По стандарту С++, конверсия между void* и void(*)() невозможна; другое дело, что некоторые компиляторы для некоторых платформ (одно из требований — это tiny|large|flat модель памяти) на это плюют.
Отстал, наверное, я от жизни.
А что, стандарт Си++ и такие конструкции запрещает?
union {
void *p;
void (*fp)();
};
P.S. Прошу прощения, если задерживаюсь с ответами на посты.
То RSDN упадет, то работы навалом...
Как освобожусь, постараюсь всем ответить.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
AVC пишет:
> Отстал, наверное, я от жизни. > А что, стандарт Си++ и такие конструкции запрещает? > >union { > void *p; > void (*fp)(); >}; > >
Нет, но тут программист сам виноват (явно пытается обойти ограничение).
Здравствуйте, Cyberax, Вы писали:
>> Отстал, наверное, я от жизни. >> А что, стандарт Си++ и такие конструкции запрещает? >> >>union { >> void *p; >> void (*fp)(); >>}; >> >> C>Нет, но тут программист сам виноват (явно пытается обойти ограничение).
Допустим.
Хотя кто-то тут утверждал, что в Си++ — "сильная типизация".
Давай-те все-таки определимся в понятиях.
А то, ИМХО, здесь путают "сильную" и "статическую" типизацию. Сильная типизация — это такая типизация, которую нельзя обойти.
В Си++ такой типизации нет. Здесь столько путей ее обхода: и явное приведение указателей, и unionы, и т.д. и т.п.
Если программист, использующий эти средства, "сам виноват", то зачем они присутствуют в языке? Чтобы потом все "списать" на программиста?
Ну, хорошо. Пусть программист "сам виноват".
Рассмотрим недавний трагикомический случай из практики.
Тестируем новый процессор.
Используемые в нем алгоритмы сначала были написаны на Си++ (программный эмулятор), а затем на VHDL.
Дошло дело до тестирования команд с плавающей точкой.
Надо "сгенерить" последовательность входных и выходных значений.
"Генерим" — какая-то "фигня" получается.
Все входные данные — одно и то же число.
В чем дело? Оказывается, программист случайно (вместе с предыдущими строками) закомментировал оператор приведения operator float().
Вот (схематично, конечно) как это произошло:
#include <stdio.h>
class Float {
float _float;
public:
Float(float x) : _float(x) { }
// следующая строка была закомментирована по ошибке (просто опечатка)
//operator float() { return _float; }
// в реальной программе bool() проверяет валидность Floatoperator bool() { return true; }
};
int main()
{
Float F = 3.1415926536f; // Кто и шутя, и скоро пожелаетъ Пи узнать число, ужъ знаетъ.float x = F;
printf("%f\n", x); // Что напечаталось? Правильно, 1.000000return 0;
}
Все компиляторы Си++, используемые нами в работе, сгенерировали неявное приведение bool к float, даже не хрюкнув!
Чудо, что за сильно типизированный язык!
Не откажу себе в удовольствии процитировать авторов книги, содержащей астрономические алгоритмы на Си++.
(Я имею в виду книгу Пфлегера и Монтенбрука "Астрономия на персональном компьютере".)
Здесь надо сказать, что по сравнению с другими языками C++ имеет много недостатков, которые затрудняют разработку сложных научных программ. В частности, у него слабая поддержка одномерных и многомерных массивов, нет локальных процедур, неудачная концепция модуля, не поддерживается проверка индексов массивов, а также выполняется неконтролируемое преобразование типов.
Привожу, как говорится, без комментариев.
Лишь замечу, что ни одного из этих недостатков нет у Оберона.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
AVC> Float F = 3.1415926536f; // Кто и шутя, и скоро пожелаетъ Пи узнать число, ужъ знаетъ.
Мне больше нравиться
'Это я знаю и помню прекрасно их многие знаки мне лишни напрасно'
Здравствуйте, Sergey J. A., Вы писали:
SJA>Здравствуйте, AVC, Вы писали:
AVC>> Float F = 3.1415926536f; // Кто и шутя, и скоро пожелаетъ Пи узнать число, ужъ знаетъ. SJA>Мне больше нравиться SJA>'Это я знаю и помню прекрасно их многие знаки мне лишни напрасно' SJA>
Применительно к float последние 2-3 цифры, конечно же, лишние.
Просто хотелось "доцитировать" до точки.
Вообще же, для запоминания числа Пи существует уйма стихов, иные из которых довольно длинные (двадцать цифр после точки ).
Стишок "кто и шутя..." был, кажется, придуман нижегородским учителем Шенроком.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
AVC,
> А что, стандарт Си++ и такие конструкции запрещает? >
> union {
> void *p;
> void (*fp)();
> };
>
Конструкцию — нет. А (предполагаемое) использование, заключающееся в записи в p с последующим чтением из fp (или наоборот) — да. Правда, контролировать компилятору/среде исполнения не предписывает, просто снимает с себя ответственность за последствия дальнейшей работы соответствующей программы.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, AVC, Вы писали:
[.....] AVC>Рассмотрим недавний трагикомический случай из практики.
[.....]
Внимательно прочитал. Откомпилировал программу. Вывела она единицу. Один пустячок: с точки зрения ОС программа отработала правильно, к теме обсуждения (защита памяти) недостаток языка C++ отношения не имеет. Это стоит обсудить где-нибудь в отдельной ветке.
AVC>Не откажу себе в удовольствии процитировать авторов книги, содержащей астрономические алгоритмы на Си++. AVC>(Я имею в виду книгу Пфлегера и Монтенбрука "Астрономия на персональном компьютере".) AVC>
AVC>Здесь надо сказать, что по сравнению с другими языками C++ имеет много недостатков, которые затрудняют разработку сложных научных программ. В частности, у него слабая поддержка одномерных и многомерных массивов, нет локальных процедур, неудачная концепция модуля, не поддерживается проверка индексов массивов, а также выполняется неконтролируемое преобразование типов.
Интересно. С удовольствием почитал бы. В такой книге может почерпнуть для себя даже очень далекий от астрономии человек.
История создания книги, полагаю, такова. Авторы накопили определенный опыт в данной предметной области и решили рассказать о нем в форме, доступной простому смертному. В издательстве им сказали, что неплохо было бы программный код представить на C++, тираж бы поднялся. (Я абсолютно уверен, что астрономы всю математику писали на Фортране). Многие, переходя с Фортрана на C++, испытывают сильный дискомфорт.
В Фортране тоже не выполняется проверка выхода за границы массива, но это никого не смущает — техника работы с массивами в Фортране отработана так, что на отсутствие проверок просто не обращают внимания. А в случае ошибки — сработает защита памяти. При переходе с Фортрана на C/C++ она действительно срабатывает слишком часто. Все дело в индексации: в Фортране она начинается с 1, в C/C++ — с 0.
А многомерных массивов нет не только в C++.
Неделю назад, буквально за минуты до падения сервера, хотел написать: как наглухо зацепиться за стек и подгадить GC.
Идея состоит в следующем.
Пусть некий активный объект владеет стеком своего потока (ну и далее оттуда растёт орграф зависимостей).
Теперь достаточно в одной из функций подцепить указатель на сам объект и уйти в бесконечность. Всё, мы получили вешалку, за которую можно цеплять что угодно (например, активный объект содержит коллекцию указателей на сторону).
Кстати, скорее всего, объект с самого начала зацеплен за стек своего потока.
Разумеется, можно обнаружить, что часть объектов недоступна из корня орграфа (корнем является стек главного потока). Тогда встанет вопрос: а как же грамотно убить сирот? Пассивный объект — нет проблем: разорвали граф, поубивали участников. Но у активного графа есть действующий поток, как его останавливать?
Кстати о бесконечном цикле.
Разумеется,
while(evertrue()) { ..... }
является ошибкой в данном конкретном месте программы.
Однако можно же сделать и по-другому:
take(semaphore, INFINITE);
а клиент забудет выполнить действия, приводящие к give.
За неимением оберона, ставил эксперименты на python. Единственный способ замочить забытый поток — это послать интерпретатору сигнал term или kill.
from threading import *
class Orphan(Thread) :
name = ""
evt = 0
def goodbye(self) :
self.evt.set()
def __init__(self,n) :
Thread.__init__(self)
self.evt = Event()
self.name = n
def run(self) :
print self.name,"started"
self.evt.wait()
print self.name,"finished"
def fire(n) :
t = Orphan(n)
t.start()
return t
# запустили...
t1 = fire("First")
t2 = fire("Second")
# отсигналили только одному
t1.goodbye()
#t2.goodbye()
# потеряли указатели
t1 = 0
t2 = 0
print "The end"
Здравствуйте, Privalov, Вы писали:
AVC>>Рассмотрим недавний трагикомический случай из практики. P>Внимательно прочитал. Откомпилировал программу. Вывела она единицу. Один пустячок: с точки зрения ОС программа отработала правильно, к теме обсуждения (защита памяти) недостаток языка C++ отношения не имеет. Это стоит обсудить где-нибудь в отдельной ветке.
Обсуждение языка и ОС Оберон у нас постоянно пересекаются.
Ведь ОС Оберон основывается именно на свойствах одноименного языка.
(Думаю, именно поэтому они носят одно и то же имя.)
Тема же "сильной типизации Си++" была поднята не мной, а WolfHound.
В чем я с ним, конечно, не согласен.
AVC>>Не откажу себе в удовольствии процитировать авторов книги, содержащей астрономические алгоритмы на Си++. AVC>>(Я имею в виду книгу Пфлегера и Монтенбрука "Астрономия на персональном компьютере".) AVC>>
AVC>>Здесь надо сказать, что по сравнению с другими языками C++ имеет много недостатков, которые затрудняют разработку сложных научных программ. В частности, у него слабая поддержка одномерных и многомерных массивов, нет локальных процедур, неудачная концепция модуля, не поддерживается проверка индексов массивов, а также выполняется неконтролируемое преобразование типов.
P>Интересно. С удовольствием почитал бы. В такой книге может почерпнуть для себя даже очень далекий от астрономии человек.
Книга выпущена в 2002 году издательством "Питер". http://shop.piter.com/book_about.phtml?id=978531800223&web_ok=
Правда, говорят, что найти ее в продаже уже не так просто.
P>История создания книги, полагаю, такова. Авторы накопили определенный опыт в данной предметной области и решили рассказать о нем в форме, доступной простому смертному. В издательстве им сказали, что неплохо было бы программный код представить на C++, тираж бы поднялся. (Я абсолютно уверен, что астрономы всю математику писали на Фортране). Многие, переходя с Фортрана на C++, испытывают сильный дискомфорт.
Полную историю книги не знаю.
Знаю только, что предыдущее издание книги содержало программы на Паскале.
Отсюда, видимо, и некоторое разочарование авторов в Си++.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
AVC пишет:
> C>Нет, но тут программист сам виноват (явно пытается обойти ограничение). > Допустим. > Хотя кто-то тут утверждал, что в Си++ — "сильная типизация". > Давай-те все-таки определимся в понятиях. > А то, ИМХО, здесь путают "сильную" и "статическую" типизацию. > *Сильная* типизация — это такая типизация, которую *нельзя* обойти.
Нет. Сильную типизацию нельзя обойти НЕЯВНО.
А руками _заставить_ привести — очень даже и можно ...
> В Си++ такой типизации нет. Здесь столько путей ее обхода: и явное > приведение указателей, и *union*ы, и т.д. и т.п. > Если программист, использующий эти средства, "сам виноват", то зачем > они присутствуют в языке?
Затем, что иногда бывают полезны для других целей. Классический пример:
union BIGINT
{
struct Ints
{
int i1,i2;
};
struct Bytes
{
byte b1,b2,b3,b4,b5,b6,b7,b8;
};
}
> Используемые в нем алгоритмы сначала были написаны на Си++ > (программный эмулятор), а затем на VHDL. > *Все* компиляторы Си++, используемые нами в работе, сгенерировали > *неявное* приведение bool к float, даже не хрюкнув!
Есть такая проблема — все дело в том, что bool был добавлен в язык очень
поздно. Кстати, MSVC на такой код выдает предупреждение.
> Чудо, что за *сильно типизированный язык*!
А он вполне сильно типизирован. И преобразование bool->float вполне себе
валидно.
> Не откажу себе в удовольствии процитировать авторов книги, содержащей > астрономические алгоритмы на Си++. > (Я имею в виду книгу Пфлегера и Монтенбрука "Астрономия на > персональном компьютере".) > Здесь надо сказать, что по сравнению с другими языками C++ имеет много > недостатков, которые затрудняют разработку сложных научных программ. В > частности, у него слабая поддержка одномерных и многомерных массивов, > нет локальных процедур, неудачная концепция модуля, не поддерживается > проверка индексов массивов, а также выполняется неконтролируемое > преобразование типов.
Да, да, конечно же. Всякие uBlas, и т.п. — все полная фигня.
И еще С++ неприспособлен для векторных вычислений, о чем наглядно
свидетельствует http://www.pixelglow.com/macstl/
И для параллельного программирования тоже не приспособлен, так как
документа http://www.openmp.org/drupal/mp-documents/cspec20_bars.pdf нет
в природе.
> Привожу, как говорится, без комментариев. > Лишь замечу, что ни одного из этих недостатков нет у Оберона.
Hello, Cyberax!
You wrote on Tue, 08 Feb 2005 12:40:32 GMT:
C>>> Нет, но тут программист сам виноват (явно пытается обойти C>>> ограничение).
??>> Допустим.
??>> Хотя кто-то тут утверждал, что в Си++ — "сильная типизация".
??>> Давай-те все-таки определимся в понятиях.
??>> А то, ИМХО, здесь путают "сильную" и "статическую" типизацию.
??>> *Сильная* типизация — это такая типизация, которую *нельзя* обойти.
C> Нет. Сильную типизацию нельзя обойти НЕЯВНО.
Вообще-то общепринято называть сильной типизацию, которую вообще нельзя
обойти. Тут, правда, есть другая проблема — для общения с внешним миром
(написания библиотек ввода-вывода и т.п.) языки с сильной типизацией не
годятся. А сильная статическая типизация в языке общего назначения — вообще
нонсенс.
With best regards, Sergey.
Posted via RSDN NNTP Server 1.9
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Костя Ещенко, Вы писали:
КЕ> ну вы блин даете... КЕ>А если бы потребовалось возвращать знак числа, то добавили бы приведение к int?
Видно, возмущение было столь сильным, что на критику уже слов не хватило?
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, Павел Кузнецов, Вы писали:
>> А что, стандарт Си++ и такие конструкции запрещает? >>
>> union {
>> void *p;
>> void (*fp)();
>> };
>>
ПК>Конструкцию — нет. А (предполагаемое) использование, заключающееся в записи в p с последующим чтением из fp (или наоборот) — да. Правда, контролировать компилятору/среде исполнения не предписывает, просто снимает с себя ответственность за последствия дальнейшей работы соответствующей программы.
Я так и предположил: чтобы "списать" все беды на программиста.
Вообще, интересное поведение компилятора: он не контролирует запрещенную конструкцию.
Так что, когда говорят о "сильно типизированном Си++", мне почему-то вспоминается "перл" одного футбольного комментатора:
Несмотря на хорошую погоду, многие болельщики предпочли переждать дождь дома.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
AVC пишет:
> Я так и предположил: чтобы "списать" все беды на программиста. > Вообще, интересное поведение компилятора: он *не контролирует > запрещенную конструкцию*.
Еще раз: эта конструкция *НЕ* запрещена, она полностью семантически и
синтаксически правильна, и может быть использована во вполне нормальных
целях. Union'ы _явно_ были введены в Стандарт именно для специальных
трюков с битами.
Кстати, лично я не представляю, как такую конструкцию можно написать
случайно. Ну а то что С и С++ дают достаточно средств, чтобы эффективно
выстрелить себе в ногу — давно известно.
Здравствуйте, Cyberax, Вы писали:
C>AVC пишет:
>> *Сильная* типизация — это такая типизация, которую *нельзя* обойти. C>Нет. Сильную типизацию нельзя обойти НЕЯВНО. C>А руками _заставить_ привести — очень даже и можно ...
В том-то и проблема, что в Си++ нельзя отличить программы, в которых было использовано такое "приведение руками", от программ, в которых такого приведения не было.
>> В Си++ такой типизации нет. Здесь столько путей ее обхода: и явное >> приведение указателей, и *union*ы, и т.д. и т.п. >> Если программист, использующий эти средства, "сам виноват", то зачем >> они присутствуют в языке?
C>Затем, что иногда бывают полезны для других целей. Классический пример: C>
О чем я и говорил: сильной типизации в Си++ нет.
>> Используемые в нем алгоритмы сначала были написаны на Си++ >> (программный эмулятор), а затем на VHDL. >> *Все* компиляторы Си++, используемые нами в работе, сгенерировали >> *неявное* приведение bool к float, даже не хрюкнув! C>Есть такая проблема — все дело в том, что bool был добавлен в язык очень C>поздно. Кстати, MSVC на такой код выдает предупреждение.
Еще раз проверил на MSVC. Опять без warningов.
>> Чудо, что за *сильно типизированный язык*! C>А он вполне сильно типизирован. И преобразование bool->float вполне себе C>валидно.
Правда?!
А вот мне, дурню, кажется, что между bool и float нет ничего общего.
Поэтому и неявное преобразование недопустимо.
>> Не откажу себе в удовольствии процитировать авторов книги, содержащей >> астрономические алгоритмы на Си++. >> (Я имею в виду книгу Пфлегера и Монтенбрука "Астрономия на >> персональном компьютере".) >> Здесь надо сказать, что по сравнению с другими языками C++ имеет много >> недостатков, которые затрудняют разработку сложных научных программ. В >> частности, у него слабая поддержка одномерных и многомерных массивов, >> нет локальных процедур, неудачная концепция модуля, не поддерживается >> проверка индексов массивов, а также выполняется неконтролируемое >> преобразование типов. C>Да, да, конечно же. Всякие uBlas, и т.п. — все полная фигня. C>И еще С++ неприспособлен для векторных вычислений, о чем наглядно C>свидетельствует http://www.pixelglow.com/macstl/ C>И для параллельного программирования тоже не приспособлен, так как C>документа http://www.openmp.org/drupal/mp-documents/cspec20_bars.pdf нет C>в природе.
Подождите.
Ведь в приведенной мной цитате все правда.
Многомерных массивов нет.
Модулей нет.
Индексы — если и можно контролировать, то только в отдельных случаях.
Пример неконтролируемого приведения типов я только что привел.
Если Вы с этими утверждениями не согласны, то оспорьте их.
А существование где-то там пары навороченных библиотек не имеет к данному вопросу никакого отношения.
>> Привожу, как говорится, без комментариев. >> Лишь замечу, что ни одного из этих недостатков нет у Оберона. C>У этого уродца вообще ничего нет.
Я так понял, что разумные аргументы закончились?
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
AVC>Многомерных массивов нет.
Конечно, я имел в виду: гибких многомерных массивов.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
КЕ>> ну вы блин даете... КЕ>>А если бы потребовалось возвращать знак числа, то добавили бы приведение к int?
AVC>Видно, возмущение было столь сильным, что на критику уже слов не хватило?
На самом деле, возмущение справедливое.
1) Если предусмотрено приведение к нескольким разным типам, то по можно предположить, что полученные значения коррелируют. Например, контейнер строки может отдавать const char*, bstr_t и т.п.
В тех же случаях, где результат серии преобразований носит разрушительный характер, то лучше избегать неявностей.
Кстати, отчасти поэтому в С++ введены две фичи:
* не более одного неявного преобразования в выражении
* явные (explicit) конструкторы
2) Практика показывает, что приведение к bool носит двоякий характер:
* по смыслу — проверка валидности, непустоты и т.п.
* по форме — сравнение с нулём.
В случае числовых типов сравнение с нулём обычно определено; поэтому вводить дополнительно operator bool(), несущий иной смысл — это рассогласовывать форму и содержание.
3) Операторы неявного приведения типа нужны для
* уменьшения писанины (применения функций/методов/операторов явного приведения)
* единообразия (особенно, при подстановке в шаблоны)
Но поскольку для встроенных типов приведение к bool — это проверка на 0, то кардинально иной смысл приводит к нарушению работы алгоритма. Вместо этого лучше параметризовать алгоритм предикатом.
В случае с Float — нужен ли был этот оператор, или просто руки шаловливые оказались?
Пример кода
float x;
Float X;
if(x) { ... } // если y != 0if(X) { ... } // если x валидный? если x != 0?if(x!=0) { ... } // предположительно, здесь компилятор может оптимизировать, увидев литеральный 0if(X!=0) { ... } // возможно, что сравнение с целым нулём - дороже, чем просто проверка на 0if(is_nonzero(x)) { ... } // инлайнится в y!=0if(is_nonzero(X)) { ... } // эффективная реализация предиката - на усмотрение разработчикаif(is_valid(x)) { ... } // если такие задачи встречаются, то можно реализовать.if(is_valid(X)) { ... } // явная замена двусмысленному operator bool
4) Наконец, компилятор VC даёт предупреждение о приведении к bool и из bool в число. (Про другие компиляторы — врать не буду). Кому хочется развлечений — включайте опцию "treat warnings as errors" и наслаждайтесь.