Страниц: 1 [2]
  Печать  
Автор Тема: внутренняя ошибка компилятора  (Прочитано 18697 раз)
olej
QOR.Team
****
Offline Offline

Сообщений: 42



Просмотр профиля
« Ответ #15 : Марта 26, 2002, 01:54:00 pm »

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

Память может стать "дырявой", но к скорости это не имеет отношения: при отсутствии виртуализации страниц на диск адресация идёт по прямым указателям (а в QNX код никогда не виртуализируется, а данные - иногда, и не в real-time). Память может просто исчерпаться при наличии достаточного суммарного объёма, это да. Но в C++ можно переопределить для класса new() & delete, с тем, например, чтобы небольшие объекты выделять из отдельного крупного ариала памяти, и следить за эффективностью его использования.


тут я сошлюсь еще и на обзор dedicated-systems:
"what makes a good rtos? "
на сегодня, пишут там, С++ и Java не есть правильный выбор для разработки приложений жестокого реального времени (там они рассуждают как раз и про сборку мусора).

Одно и другое (C++ & Java) радикально отличаются. Java действительно построена вся на сборке мусора - там нет указателей (хотя почти всё, что там есть - это ссылки!). Использовать Java в real-time - это, мне кажется просто "дикая" идея - с моделированием (интерпретацией) byte-кода... (ну JIT - но там: одно находим, другое теряем).

В C++, если каждому new у вас соответствует delete, проблем ни с памятью, ни с "мусором" не может возникать в принципе (так же, как и в C). Проблема в том, что в действительно "крупном" проекте гарантировать такую идеальную "парность" new &  delete ... проблематично. И в этом - основная масса ошибок. Но в классическом C, за счёт отсутствия не только именной, но даже структурной типизации (по типу Pascal) - количество ошибок можно ожидать ... ну, так 10:1 или 100:1 (относительно C++).

Эффективность генерируемого кода C & C++ практически одинакова (за исключением, пожалуй, одного места - косвенного вызова виртуальных методов через таблицу, но эта одна косвенность - слёзы). И эффективность эта весьма приближается к ассемблерному коду.

Вот и возникают в связи с этим неясности в использовании языков программирования

Вот я и говорю: давайте обратимся к dmi и попросим создать раздел "Языки программирования". Именно раздел, а не тему, т.к. всё, что относится к Perl неинтересно тем, которые C++

буду благодарен, если сделаете пояснения или дадите ссылки на литературу

Есть действительно языки реального времени, включающие эти особенности в свой синтаксис (и семантику): группа Modula, Oberon, Ada... Хорошая новость: в рамках проекта GNAT сделана поддержка gcc для Ada95, и она будет включаться в последующие версии...

Пожалуй лучшая книга "как это должно слелать" - это Р.Янг "Языки программирования реального времени". Но я знаю издание где-то 2-й половины 80-х, было ли позже не знаю. Поищите.

Кроме того, для общего понимания real-time механики очень интересны вообще все публикации (кроме рекламы ) по Ada. Им несть числа!
Записан
Evgeniy
Jr. Member
**
Offline Offline

Сообщений: 73


Просмотр профиля
« Ответ #16 : Марта 26, 2002, 06:19:00 pm »


andrew пишет:
в процессе работы создаются, удаляются классы (чьи-то наследники
и предки) и т.д.


Уважаемый andrew, в процессе работы C++ программы не создается и не удаляетси НИ ОДИН КЛАСС - это привелегии ОБЪЕКТНЫХ интерпретирующих систем типа SmallTalk, а не объекноОРИЕНТИРОВАННЫХ компилируемых языков, к которым и относится C++.

Вопрос фрагментации глобальной динамической памяти, конечно, существует, но в этом смысле сишный malloc()/free() ничем не лучше, а с учетом отсутствия конструкторов-деструкторов еще и опаснее.
Кстати, если мне не изменяет память, то упомянутый Qlej Янг вообще советует по возможности избегать динамики распределения heap-памяти - в крайнем случае делать это при старте-завершении программы.
О накладных расходах позднего связывания Olej уже сказал.
Проблема "неэффективности" "плюсов" лежит в совсем другой плоскости - кажущаяся простота повторного использования кода приводит к очень неаккуратному программированию, "грязному" проектированию системы классов, использованию плохо подходящих родительских классов, и как результат огромному объему мертвого ненужного кода и жуткой глубине вызовов. Этому же способствует слабая поддержка inline кодирования для функций доступа к элементам классов и тотальное применение с-интерфейса для пущей совместимости. "Следовательно, разруха не в клозетах, а в головах!"

Кстати, Olej, вы пишете


...Но в классическом C, за счёт отсутствия не только именной, но даже структурной типизации (по типу Pascal)...


Мне кажется, что здесь вы несколько ошибаетесь - Pascal (и все его потомки) как раз базируется на именной эквивалентности типов - попробуйте ввести новое имя для integer и применить его в одном выражении с int и посмотрите на результат. Структурная же эквивалентность используется в A68.

Ну а в классическом C есть только видимость типизации. Это же очень часто относится и к "плюсам" в силу стремления к совместимости с прородителем.
Записан
andrew
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #17 : Марта 27, 2002, 02:32:00 am »

спасибо за пояснения! ).

Еще несколько замечаний по поводу сборки мусора в С++.
Действительно, стандарт С++ не гарантирует, чтобы в его состав
входил этот самый сборщик мусора. Но в последнее время для ряда систем предпочтительнее управлять распределением памяти в ручную.
Ряд реализаций С++ предполагают его наличие. При этом для С++ подходит сборщик мусора, который размещает объекты в памяти, так чтобы ее фрагментация была минимальной Для небольших программ желательно вообще обходиться без сборки (Страуструп).

В связи с этим вопрос: а как убедиться, есть ли сборка мусора
в этой версии С++?

Непонятно также, почему при всех преимуществах С++ Neutrino написано на C?




[ Это Сообщение было отредактировано: andrew в 2002-03-26 23:37 ]
Записан
olej
QOR.Team
****
Offline Offline

Сообщений: 42



Просмотр профиля
« Ответ #18 : Марта 27, 2002, 07:19:00 am »


Evgeniy пишет:
Мне кажется, что здесь вы несколько ошибаетесь - Pascal (и все его потомки) как раз базируется на именной эквивалентности типов - попробуйте ввести новое имя для integer и применить его в одном выражении с int и посмотрите на результат. Структурная же эквивалентность используется в A68.

Может быть. Но мне кажется, и сильно кажется, что в классическом Pascal от Вирта (об этом, кажется, было у Вирта и того же Р.Янга) - именно структурная типизация, т.к. это один из первых опытов строго типизированных языков, и они дальше не пошли.

Во всех последователей (я года 2 работал с TopSpeed Modula-2) - да, там только именная, как и в C++. Как в том общеприменимом Pascal-уродстве, который Delphy - я просто не знаю.


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

В связи с этим вопрос: а как убедиться, есть ли сборка мусора
в этой версии С++?

Ну нету, нету там сборки мусора!!!

Страуструп действительно описывает "ручную" сборку мусора там, где ему нужно показать переопределение new(), но везде объясняет: почему мы отказались от идеи "автоматической" сборки мусора в стандарте ANSII v2!

Если кому не нравится стандарт ANSII и ему "горит" приделать туда сборку мусора,  то всё дальнейшее - исключительно ЕГО проблемы!
Записан
andrew
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #19 : Марта 27, 2002, 12:41:00 pm »

Я благодарен Olej за ответы, несмотря на их некоторую эмоциональность.

Вопросы остаются.
По-видимому,есть смысл организовать отдельный
раздел по языкам программирования,
как и было предложено.
Записан
olej
QOR.Team
****
Offline Offline

Сообщений: 42



Просмотр профиля
« Ответ #20 : Марта 27, 2002, 02:35:00 pm »

andrew пишет:
Я благодарен Olej за ответы, несмотря на их некоторую эмоциональность.
Вопросы остаются.
По-видимому,есть смысл организовать отдельный
раздел по языкам программирования,
как и было предложено.

Sorry, это не эмоциональность - это я шучу так неудачно
По вопросу организации раздела уже отослал письмо dmi.
Записан
Evgeniy
Jr. Member
**
Offline Offline

Сообщений: 73


Просмотр профиля
« Ответ #21 : Марта 27, 2002, 03:00:00 pm »


В связи с этим вопрос: а как убедиться, есть ли сборка мусора
в этой версии С++?

Непонятно также, почему при всех преимуществах С++ Neutrino написано на C?


Ну пока спецфорума по языкам нет, а "вопросы остаются" - продолжу здесь

На первый вопрос ответить можно так: только по документации .
Насколько мне известно, gcc не поддерживает сборку мусора.
У меня есть большие сомнения в принципиальной реализуемости КОРРЕКТНОЙ сборки мусора в C++.
И вот по какой простой причине.
Дело в том, что сборка мусора должна обеспечивать освобождение памяти объектов, на которые нет ссылок. Это предполагает отслеживание ВСЕХ присваиваний указателей и их коррекцию после сборки мусора, т.е. требует не только дополнительных модулей run-time, но и соответствующей генерации кода. И это было бы не смертельно - проблема возникает "благодаря" совместимости с C, в котором есть адресная арифметика, а значит и возможности вычисления и запоминания взаимных размещений объектов в виде смещений. Не будем здесь обсуждать вопрос разумности и этичности применения этих средств. Но т.к. они присутствуют в языке - они должны учитываться. А поскольку сборка мусора всегда приводит к изменению взаимного размещения объектов в памяти (иначе она просто не нужна), то необходимо отслеживать ВСЕ адресные вычисления, что в данном случае невозможно.
Есть и другие моменты в языке, которые делают применение сборки мусора в C++ малоцелесообразным - например возможность появления "висячих" ссылок - ссылок на несуществующие объекты - одна из самых распространенных ошибок в C.

Ответ на второй вопрос совсем прост - "наследие проклятого прошлого" .
Ведь система-то начиналась задолго до появления "плюсов". Кроме того, какими бы малыми не были дополнительные накладные расходы на "плюсы", я не вижу особого смысла в них применительно к ядру и базовым средствам ОС - ну не нужно там позднего связывания, а кушать ресурсы оно будет. Тем более во встраиваемой ОС. Имело бы смысл применение чего-то качественно другого типа - той же Ada или Modula-2, но это потребовало бы дополнительных и немалых ресурсов для перехода на новые средства (новый инструментарий, переобучение персонала, сложность заимствования частей старого кода и т.д).
Т.е. вопрос перехода к другому языку для реализации новой, пусть и сильно переработанной версии системы сводится к вопросам вложения денег и стереотипности мышления.
Записан
andrew
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #22 : Марта 28, 2002, 02:29:00 am »

Понятно.
Тема оказалась более интересной,
чем я думал изначально.
Записан
dmi
QOR.Admin
*****
Offline Offline

Сообщений: 469



Просмотр профиля
« Ответ #23 : Марта 28, 2002, 04:35:00 am »


По вопросу организации раздела уже отослал письмо dmi.


Получение письма подтверждаю
Форум к понедельнику сделаю.
Записан
int19h
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #24 : Апреля 01, 2002, 06:51:00 pm »

Сборщики мусора для C и подобных языков есть - правда, все мне известные почему-то под Вынь. И, кстати, с адресной арифметикой весьма неплохо справляются - при условии невыхода указателя за пределы отведенного блока все корректно работает. Единственная проблема - невалидные указатели: в union'ах, или просто приведенное число...
Записан
Evgeniy
Jr. Member
**
Offline Offline

Сообщений: 73


Просмотр профиля
« Ответ #25 : Апреля 01, 2002, 08:54:00 pm »

Уважаемый int19h!

По этому поводу у меня к Вам есть несколько вопросов, но я решил, что эту тему пора переносить в раздел "Языки программирования и алгоритмы" - посмотрите, пожалуйста, там.

Извините за неудобство!
Записан
187
Гость
« Ответ #26 : Апреля 18, 2002, 11:48:00 pm »


Непонятно также, почему при всех преимуществах С++ Neutrino написано на C?

потому-что для с++ для каждого (почти) обращения к переменной/функции класса идет 2 обращения к памяти, а это лишних 5 байт, учитывая, что переменных и функций много и работа с ними идет интенсивная (я так полагаю ) то этот привесок может стать критическим для микроядерных систем, тем более что с++ хуже поддаётся оптимизации. опять же лишние такты.. ведь qnx не толь ко на пнях 4-х гоняют , лишнее обращение к памяти это 1-2 такта проца при кэш попадании, и несколько тактов сис шины при кэш промахе (а что вы думали память за такт все выдаст Ж%) ), а промахи бывают часто осбенно если задач гонится много и у них данных немало. а то что там страуструп пишет (кстати это он или она?) то просто раскомпилируйте чтонибудь не слишком просто/банальное скомпилированое на с++ и посмотрите. за удобство программирования платить приходится вот так.
Записан
olej
QOR.Team
****
Offline Offline

Сообщений: 42



Просмотр профиля
« Ответ #27 : Апреля 19, 2002, 05:49:00 am »


187 пишет:
потому-что для с++ для каждого (почти) обращения к переменной/функции класса идет 2 обращения к памяти, а это лишних 5 байт, учитывая, что переменных и функций много и работа с ними идет интенсивная

Конечно, компилятор компилятору - рознь, да ещё ситуация может меняться в зависимости от уровня оптимизации. Но, в принципе, обращение к членам класса в хорошем компиляторе не требует лишних обращений (косвенности). За одним исключением - если эти члены virtual. Я не проверял это для GCC, но проверял в MS VCPP. Утверждается, что GCC - компилятор высокого уровня оптимизации, думаю что там нужно ожидать того же.

страуструп пишет (кстати это он или она?)

Это - он, чуть не сказал "оно"

то просто раскомпилируйте чтонибудь не слишком просто/банальное скомпилированое на с++ и посмотрите.

То что я описал выше - я и смотрел, но хотел бы заметить, если кто найдёт время провести такой эксперимент: что "слишком просто/банальное", что самое забубённое - компилиться оно будет одинаково, поэтому проверить это достаточно просто.
 
Записан
Evgeniy
Jr. Member
**
Offline Offline

Сообщений: 73


Просмотр профиля
« Ответ #28 : Апреля 19, 2002, 01:53:00 pm »


Olej пишет:
...Но, в принципе, обращение к членам класса в хорошем компиляторе не требует лишних обращений (косвенности). За одним исключением - если эти члены virtual.


Мне так думается - спецом не проверял - что косвенность необходима несколько чаще. А именно во всех методах класса при обращении к атрибутам класса т.к. неявно предполагается что это this->....
А вот с virtual это скорее всего обязательно только в случае работы через указатель на объект (то что они называют "полиморфизмом объектов") - там прежде чем добраться к методу класса надо прогуляться к описателя класса данного объекта. Тут получится как минимум два дополнительных разименования. В случае же прямого обращения к методу объекта класса (не через указатель на объект) требуемая функция может быть определена статически независимо от атрибута виртуальности.
Записан
olej
QOR.Team
****
Offline Offline

Сообщений: 42



Просмотр профиля
« Ответ #29 : Апреля 19, 2002, 05:29:00 pm »


Evgeniy пишет:
Мне так думается - спецом не проверял - что косвенность необходима несколько чаще. А именно во всех методах класса при обращении к атрибутам класса т.к. неявно предполагается что это this->....

Если "атрибуты" имелись в виду члены, то все они статически определённые на этапе компиляции, и адресуются индексно, что нибудь так: this[member]->. То-же самое и к функциям-членам: адресация к ним происходит точно также, как к и внешним функциям C (статически), но им передаётся 1-й неявный параметр (сверх указанных вами) - this. А с обращениями внутри функции к членам переменным - так как в предыдущем пункте через этот 1-й переданный параметр. Т.е. никаких дополнительных накладных расходов не возникает. (Ну, разве что компилятор со-о-о-всем тупой - студенческая какая-то работа).




[ Это Сообщение было отредактировано: Olej в 2002-04-19 14:32 ]
Записан
Страниц: 1 [2]
  Печать  
 
Перейти в: