Здравствуйте, Klatu, Вы писали:
K>И ты за всем пустословием упустил самое главное. В управляемом коде надо еще постараться, чтобы получить наведенную ошибку. А в С++ надо очень постараться, чтобы их не получить.
Теоретик?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Sinclair, Вы писали:
ГВ>>"Традиционные" менеджеры памяти — это какие? Из MSC RTL? Так с ними сравнивать бессмысленно — там одна только блокировка/разблокировка хипа чего стоит. S>Это любые, где требуются явные операции освобождения памяти.
Один мой такой "любой" аллокатор в КСВшном сраче на спор порвал GC в тесте производительности, предложенном .NETчиками.
Так что аллокаторы они пц какие разные бывают.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Sinclair, Вы писали:
C>>Продвинутые аллокаторы используют локальные для потоков арены, там блокировка не нужна. S>Тем не менее, независимо от степени продвинутости аллокатора, при убийстве 100к объектов нужно 100к раз вызвать код возврата памяти в кучу.
Это считанные такты в нормальных реализациях. GC этого же колва объектов будет дороже.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Геннадий Васильев, Вы писали:
S>>На практике даже заменой стандартного аллокатора занимаются единичные мегагуры C++. ГВ>Ну что ж, спасибо за комплимент. Надо сказать, весьма неожиданно для этого форума.
Обычно применяемый ими термин скорее оскорбителен.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, gandjustas, Вы писали:
G>в C++ для такого поведения нужны различные умные указатели, аллокаторы и другие далеко нетривиальные конструкции, подсильные только гуру, чтобы все работало с такой же надежностью и эффективностью.
О боги! Что же тогда из себя представляет средний С#-пник если применение готового умного указателя это считается за уровень гуру?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Banned by IT, Вы писали:
C>>В чём отличие конского навоза от свиного? BBI>А ты гурман!
Ну в целом, обоих навозов я перекидал тонны. Это гораздо более предпочтительное занятие, чем писать на Модула-2.
Здравствуйте, Banned by IT, Вы писали:
S>>>На практике даже заменой стандартного аллокатора занимаются единичные мегагуры C++. ГВ>>Ну что ж, спасибо за комплимент. Надо сказать, весьма неожиданно для этого форума. BBI>Обычно применяемый ими термин скорее оскорбителен.
Не знаю, я читать мысли не умею. Хотя, справедливости ради, время от времени чувствую себя, как в башне из слоновой кости: у них там какие-то хождения по памяти при Луне, мегагуры с продвинутыми техниками, которые я считаю тривиальными. Чистая фэнтезятина, ни дать, ни взять.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Хотя, справедливости ради, время от времени чувствую себя, как в башне из слоновой кости: у них там какие-то хождения по памяти при Луне, мегагуры с продвинутыми техниками, которые я считаю тривиальными. Чистая фэнтезятина, ни дать, ни взять.
Аналогичен до безобразия.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Banned by IT, Вы писали:
BBI>Это считанные такты в нормальных реализациях.
умножить на 100000. BBI>GC этого же колва объектов будет дороже.
Совершенно верно. Именно поэтому GC неэффективен там, где много объектов выживают.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, gandjustas, Вы писали:
G>Неверно Ocaml и Хаскел являются управляемыми языками. В сгенерированном код есть метаданные, которые позволяют использовать безопасные конструкции. G>Естественно обращение к метаданным небесплатно. В этом и суть управляемых языков и их отличия от неуправляемых.
Нет, никаких метаданных не остается, у них обратная философия все что можно должно быть разрешено в момент
компиляции и оба выдают чистый машинный код, хотя OCaml может компилировать и в байт код своей виртуальной машины.
У OCaml'а код во многом даже более кошерный чем у C++, RTTI практически отсутствует.
G>При этом для неуправляемых языков гораздо проще писать программу, которая дает предсказуемый нативный код, поэтому и называют языки native.
Здравствуйте, mrTwister, Вы писали:
T>Ну ты сравнил попу с пальцем! Без твоего, как автора кода, желания никто не заставит тебя сохранить null, в отличии от C++, где как бы ты аккуратно не писал, любой сторонний компонент может испортить твою память. Даже если этот компонент сам-по себе написан аккуратно, используя современные техники С++. Например, из-за ошибок связанных с concurrentcy, либо из-за того, что этот компонент как-то не так использовали.
ЧСХ, без моего желания C++ тоже не начнёт вольным образом реинтерпретировать память. А ошибки, связанные с нарушениями инвариантов могут быть абсолютно в любом коде — managed, unmanaged, свой, чужой — без разницы.
V>>Ну так напомню, что ты и тебе подобные постоянно игнорируют тот факт, что всякие переполнения буфера происходят в основном в legacy-коде, который был писан черти когда на голом С или на самых первых версиях C++, на котором все-равно писали как на С. Уже более 10-15 лет никто не создает в С++ массивы памяти вручную. Стал бы ты, даже имея такую возможность в дотнете (а она есть, через класс Marshal) выделять и вручную следить за блоками памяти? Это же жутко неудобно! Аналогично и в С++ — использование безопасных библиотек удобнее гораздо, банально меньше кода, и голова не болит следить за байтами.
T>Не забывай про concunrrncy. Если будет ошибка в синхронизации в управляемом коде, то испортятся только те данные, которые непосредственно участвуют в алгоритме. В случае ошибки в синхронизации нейтив кода можно начать стрелять вообще по всей памяти. Подобные ошибки — это полный ад, врагу не пожелаешь.
Мои сугубо практические наблюдения говорят о том, что managed в состоянии подкинуть сюрпризы покруче. Чуть пониже расскажу одну историю.
V>>Откуда же такое внимание к ошибкам именно в нейтиве? T>Потому что поиск и исправление бага в нейтив коде стоит на порядок дороже поиска и исправления бага в управляемом коде. Тому есть несколько причин:
Некоторое время назад (не прошло и эм-м-м... примерно тридцати месяцев с тех пор) мне довелось лечить одну ошибку в комплексе managed+unmanaged. Классика жанра: AVE, чёрт-те что на выходе из unmanaged и далее по списку. Я когда увидел — ну всё, думаю, вот оно, тайное колдунство unmanaged. Добегался по форумам за "дотнетчиками", задавака хренов — вот сам теперь по носу своему задранному и получил. А ведь говорили, предупреждали хором: тайные ошибки — это вотчина unmanaged, и делают их не только вчерашние студенты. Короче, сел на измену, долго и тщательно копал — ничего. Ну, думаю, страус твои перья — и правда, пора C++ выкидывать, раз даже я в нём разобраться не могу. Короче, дня два или три я просидел на этой, довольно крутой измене, но как я ни искал ошибку в unmanaged — ни-фи-га. Поскольку код был мой, осознание этого факта добавляло мне острых ощущений.
Потом думаю: не, что-то тут не то. Сильно не то. А, там ещё был нюанс: unmanaged-код был спроектирован исключительно под single-thread, а защиты от параллельного доступа предусмотрено не было (ради оптимизации, конечно). Естественно, были подозрения, что дело в параллельном доступе, но как-то... В общем, просматривали мы тот managed-код, но ничего подозрительного не обнаружили. Да и в остальном он работал без особых нареканий, так что, подозрения казались безосновательными.
Короче, в качестве последней надежды я поставил блокировку параллельного обращения на входе в unmanaged. Так, на всякий случай, чем чёрт не шутит?
Продолжать рассказывать или уже ясно? Да, через пару минут я получил диагностику параллельного обращения. В общем, в этом корректно работающем managed-коде была классическая concurrency-ошибка параллельного вызова того, что так вызывать в принципе нельзя, да никогда и не планировалось. Особую пикантность всей ситуации придавало то, что в остальном код работал, скажем так, вполне нормально — ну, может быть, кое-какие странности были, но мы их списывали на трудности "реальных условий". Короче: тишь, гладь, AVE, злобный C++, ухмылка Страуструпа на фоне клубов серного дыма.
Дальше всё пошло своим чередом: разобрались, поправили, вытерли пот со лба, облегчённо вздохнули. Однако я вынес из этого несколько очень полезных для себя уроков.
1) Нельзя вестись на поводу у дурацких стереотипов, что в AVE всегда виноват unmanaged. Да-да, не удивляйся, я тоже в некоторой степени подвержен этой беде: хомячий гундёж вокруг опасностей unmanaged нет-нет, да и действует даже на таких самоуверенных и упёртых ретроградов. То есть ни в коем случае нельзя полагаться на некую априорно более высокую надёжность managed. На молчаливость в случае ошибок рассчитывать можно, и на тихий омут, в котором... Конечно, само AVE кинет именно unmanaged, но далеко не факт, что из-за ошибок внутри себя;
2) Managed-код превосходно замаскировал ошибки concurrency и маскировал бы их дальше, если бы именно unmanaged не разорался во всю глотку о том, что что-то пошло не так.
3) Если бы не unmanaged, поиски тщательно замаскированной ошибки стали бы для нас чем-то вроде специальной олимпиады: главное не победа, главное — держаться подальше;
4) Ошибки в unmanaged-коде, действительно, неимоверно сложно искать... В особенности, когда их там нет и ты точно знаешь, что их там нет.
Спешу упредить возможные спекуляции: я далёк от рассуждений о чьей-то "низкой квалификации". Автор того managed-кода на самом деле весьма квалифицированный специалист и когда увидел всё это, схватился за голову, но... Не буду вдаваться в подробности, но были вполне объективные исторические причины, чтобы сложилась такая ситуация, да и вообще, настоящий профи должен лично составить полную карту граблей.
В общем, факт остаётся фактом: если бы на хвосте managed не висел сквалыга-unmanaged, ошибку пришлось бы искать гораздо дольше, а то и вообще она проплыла бы мимо. Ведь сложность поиска бага на самом деле зависит не от "управляемости" кода, а от того, какой это баг. В managed-коде причины багов ничуть не легче раскапывать, чем в unmanaged, а подчас и тяжелее из-за его всепроникающей "корректности", которая позволяет ему проглатывать то, что валит unmanaged.
У меня даже закралась крамольная мысль, что атомарность обновления ссылок в управляемом коде — не столь уж однозначно хорошая вещь. С одной стороны — дело благое: ссылка ведь не может указывать в неизвестность, правильно? Она всегда содержит либо null, либо ссылку на корректный объект. Но с другой стороны, если бы ссылки в самом деле "рушились" при несинхронизированном параллельном доступе (или ещё как-то могли быть испорчены, по крайней мере, в каком-нибудь отладочном режиме), искать ошибки было бы легче. Забавный размышлизм, верно? Гарантия корректности ссылок приводит к тому, что в некоторых ситуациях концы в буквальном смысле прячутся в воду — и хорошо, если в этой воде будет сидеть unmanaged, который добавит драйва к этому сонному царству... А иначе программа запросто может пойти в эксплуатацию с очень трудновоспроизводимой плавающей ошибкой. Managed-программа, заметь, будет управляемо и очень честно гнать пургу время от времени. И никаких тебе AVE или подозрительных падений — тишь, гладь, управляемость.
T>1) Ошибки в управляемом коде более локализованы. Одному компоненту труднее нарушить работу другого
Заблуждение. С неимоверной лёгкостью при concurrency-ошибках можно получить совместное владение одним объектом вместо двух, никто и слова худого не скажет. Один объект будет при этом ухлопан, а второй окажется в обоих потоках. И никакого шума, поскольку: а) для обновления ссылок синхронизация не требуется, б) клиент не управляет удалением объекта и там, где unmanaged непременно даст диагностику двойного удаления, managed — стоически промолчит.
Потом, например, параллельный доступ к тому же Dictionary может привести к весьма загадочным ситуациям (по этому поводу тут Klatu как-то возмущался). А поиски причин могут быть очень нетривиальными, в особенности, если этот Dictionary уедет ещё куда-то.
T>2) Наличие коллстеков у всех исключений.
Не надо преувеличивать: сам по себе коллстек показывает лишь на место возникновения сбоя, но ничего не говорит о той цепи причин, которые привели к его возникновению (кроме непосредственной). Об этом было говорено-переговорено лет семь-восемь назад.
T>3) Типобезопасность — отсутствие возможности неправильно интерпретировать память или интерфейсы.
Ещё раз повторяю для дотнетчиков: ошибки типобезопасности вычисляются и лечатся на раз. Во-первых, потому что они на самом деле встречаются нечасто; во-вторых, потому что быстро себя проявляют; а в третьих — места, где играются с приведением типов, как правило, хорошо известны и на них в случае чего напрыгивают с проверками в первую очередь (вычурные конструкции вроде reinterpret_cast придуманы не с бухты-барахты).
Исключение, как это правильно заметил vdimas, составляет legacy-код, вот там — да, свистопляска может быть какая угодно. Но я имею в виду настоящий legacy, у которого история где-нибудь лет десять или поболе, а не то, что им иногда называют (C++? Значит — legacy!) Для примера можешь скомпилировать тот же ACE (или ещё какую-нибудь старую библиотеку) — там одних только предупреждений о приведении целочисленных типов — попой ешь. Справедливости ради, других ошибок в нём тоже хватает, он же написан ради воплощения паттернов борьбы со сложностью, ну вот и... Хе-хе-хе. Но с новыми библиотеками всё намного легче: даже у такого монстра, как boost и то, предупреждения связаны в основном с использованием deprecated-функций.
Так что, всё, что ты перечислил — оно, конечно, правильно, но практика — вещь такая...
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, gandjustas, Вы писали:
_>>Кстати, с ocaml всё не совсем так. G>Что ты имеешь ввиду? Что он не использует данные о типах? Тогда как он мусор собирает?
Использует битовый тег и унифицированные блоки памяти, для того чтобы отличать то что нужно собирать.
G>Evernote был написан толпой C++ программистов. Думаю одна из причин низкой производительности была именно в этом.
Тут одно утверждение и одно предположение. Оба неверные. Толпы в EverNote никогда не было это точно.
По поводу WPF и .NET UI вообще.
UI использующий DOM (например WPF и web, browser based UI) это как правило большой набор достаточно мелких объектов которые живут в GC heap.
При этом в WPF DOM существенно низкоуровневый. Там где в browser используется один объект DOM элемент и его субобъект style (в терминах GCable сущностей) в WPF появляется примерно десяток отдельных GCable things. Т.е. WPF своей моделью создает существенную нагрузку на GC.
Особенно на этапе запуска / инициализации всего хозяйства. Для Evernote как приложения запуск как раз и есть один из частых моментов. Приложение предполагается быть легковесным в этом смысле: открыл — сделал заметку — закрыл. Нужно вспомнить что-то: открыл — посмотрел — закрыл.
Т.е. WPF для такого типа приложений очень неудачный инструмент. Для вещей типа Paint.Net он подходит наверное лучше.
Ну и потом HTML DOM скажем оперирует более высокоуровневыми конструкциями чем набор примитивов WPF. Т.е. в HTML DOM больше доля native code и memory management не связанной с GC. HTML DOM потенциально более GPU friendly. В WPF же надо конкретно знать детали имплементации чтобы достичь приемлемого результата.
Здравствуйте, Banned by IT, Вы писали: BBI>О боги! Что же тогда из себя представляет средний С#-пник если применение готового умного указателя это считается за уровень гуру?
Вот мне так интересно каждый раз это читать. На RSDN просто каждый первый плюсист непременно пользовал кастомные аллокаторы, а каждый пятый — писал свои. Голые указатели, если верить форумам, вообще никто уже десять лет не применяет. И мы, дотнетчики, сбежавшие из этого тоталитарного ада, просто зря боимся вернуться — там уже давно победила демократия и жить так же комфортно, как и в управляемом мире.
Ок, давайте возьмём какой-нибудь современный проект, существующий в реальности, а не в хвастливых рассказах.
Вот, первое, что мне попалось при поиске — Миранда. http://code.google.com/p/miranda/source/browse/trunk/miranda/src/modules/history/history.cpp
Что мы тут видим? Умные указатели?
Как бы не так!
По-прежнему незамутнённые memcpy(), C-style cast (кто там мне рассказывал про обязательность reinterpret_cast?), и явные вызовы mir_free(). О да, последнее явно говорит о собственном аллокаторе. Да вот же он: http://code.google.com/p/miranda/source/browse/trunk/miranda/src/core/memory.cpp
Упс, это всего лишь тонкий враппер вокруг malloc и free. Никаких чудес производительности от него ждать не стоит. Скорее наоборот: помимо обычного дорогого free он ещё и занимается обкладкой освобождаемой области 0xDEADBEEF.
Похоже, применение готового умного указателя — это даже выше уровня С++ гуру. Либо эти гуры все, как один, пишут не С++ код, а ехидные комменты в форумы RSDN.
Добро пожаловать в реальный мир, Нео.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Похоже, применение готового умного указателя — это даже выше уровня С++ гуру. Либо эти гуры все, как один, пишут не С++ код, а ехидные комменты в форумы RSDN.
S>Добро пожаловать в реальный мир, Нео.
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>ЧСХ, без моего желания C++ тоже не начнёт вольным образом реинтерпретировать память. А ошибки, связанные с нарушениями инвариантов могут быть абсолютно в любом коде — managed, unmanaged, свой, чужой — без разницы.
К сожалению, в сложных проектах, которые делаются более чем одной командой, еще как начинает.
T>>Не забывай про concunrrncy. Если будет ошибка в синхронизации в управляемом коде, то испортятся только те данные, которые непосредственно участвуют в алгоритме. В случае ошибки в синхронизации нейтив кода можно начать стрелять вообще по всей памяти. Подобные ошибки — это полный ад, врагу не пожелаешь.
ГВ>Мои сугубо практические наблюдения говорят о том, что managed в состоянии подкинуть сюрпризы покруче. Чуть пониже расскажу одну историю.
Тоже мне удивил. Именно про твою историю я писал следующее:
Ну ты сравнил попу с пальцем! Без твоего, как автора кода, желания никто не заставит тебя сохранить null, в отличии от C++, где как бы ты аккуратно не писал, любой сторонний компонент может испортить твою память. Даже если этот компонент сам-по себе написан аккуратно, используя современные техники С++. Например, из-за ошибок связанных с concurrentcy, либо из-за того, что этот компонент как-то не так использовали.
ГВ>2) Managed-код превосходно замаскировал ошибки concurrency и маскировал бы их дальше, если бы именно unmanaged не разорался во всю глотку о том, что что-то пошло не так.
Каким образом он их замаскировал?
ГВ>4) Ошибки в unmanaged-коде, действительно, неимоверно сложно искать... В особенности, когда их там нет и ты точно знаешь, что их там нет.
То есть другими словами, работать с unmanaged кодом очень сложно, так как если ты при работе совершишь ошибку (начнешь использовать в несколько потоков, вместо одного), то вылавить эту ошибку будет очень трудно, так как получишь произвольную стрельбу по памяти. Причем в каком коде (managed или unmanaged) ты совершишь ошибку неправильного использования unmanaged кода, в любом случае тубу будет очень весело.
ГВ>Спешу упредить возможные спекуляции: я далёк от рассуждений о чьей-то "низкой квалификации". Автор того managed-кода на самом деле весьма квалифицированный специалист и когда увидел всё это, схватился за голову, но... Не буду вдаваться в подробности, но были вполне объективные исторические причины, чтобы сложилась такая ситуация, да и вообще, настоящий профи должен лично составить полную карту граблей.
Да, это обычная ситуация.
ГВ>В общем, факт остаётся фактом: если бы на хвосте managed не висел сквалыга-unmanaged, ошибку пришлось бы искать гораздо дольше, а то и вообще она проплыла бы мимо.
С чего ты это взял? В твоем случае тебе повезло, что оно просто упало. А ведь могла вместо этого отвалиться совершенно левая функциональность, которая к данному коду вообще не имеет никакого отношения. А так радуйся, что пронесло в этот раз.
ГВ>Ведь сложность поиска бага на самом деле зависит не от "управляемости" кода, а от того, какой это баг.
Совершенно верно. При этом самые сложные для поиска баги — это баги, специфичные для С++, а именно проход по памяти, некорректная её интерпретация и пр.
ГВ>В managed-коде причины багов ничуть не легче раскапывать, чем в unmanaged, а подчас и тяжелее из-за его всепроникающей "корректности", которая позволяет ему проглатывать то, что валит unmanaged.
Легче из-а отсутствия наиболее противных багов и наличия нормальных исключений с callstack'ами и сообщениями.
ГВ>У меня даже закралась крамольная мысль, что атомарность обновления ссылок в управляемом коде — не столь уж однозначно хорошая вещь. С одной стороны — дело благое: ссылка ведь не может указывать в неизвестность, правильно? Она всегда содержит либо null, либо ссылку на корректный объект. Но с другой стороны, если бы ссылки в самом деле "рушились" при несинхронизированном параллельном доступе (или ещё как-то могли быть испорчены, по крайней мере, в каком-нибудь отладочном режиме), искать ошибки было бы легче. Забавный размышлизм, верно? Гарантия корректности ссылок приводит к тому, что в некоторых ситуациях концы в буквальном смысле прячутся в воду — и хорошо, если в этой воде будет сидеть unmanaged, который добавит драйва к этому сонному царству... А иначе программа запросто может пойти в эксплуатацию с очень трудновоспроизводимой плавающей ошибкой. Managed-программа, заметь, будет управляемо и очень честно гнать пургу время от времени. И никаких тебе AVE или подозрительных падений — тишь, гладь, управляемость.
Контракты тебя спасут. В отличии от С++, в котором даже контракты не помогут, так как ничего не стоит эти контракты кому угодно разрушить без твоего ведома.
T>>1) Ошибки в управляемом коде более локализованы. Одному компоненту труднее нарушить работу другого
ГВ>Заблуждение. С неимоверной лёгкостью при concurrency-ошибках можно получить совместное владение одним объектом вместо двух, никто и слова худого не скажет. Один объект будет при этом ухлопан, а второй окажется в обоих потоках. И никакого шума, поскольку: а) для обновления ссылок синхронизация не требуется, б) клиент не управляет удалением объекта и там, где unmanaged непременно даст диагностику двойного удаления, managed — стоически промолчит.
Локализованы — это значит, что у тебя не сломается не связанная с этими объектами функциональность. В С++ коде бывает так, что виноват один компонент, а глючит совершенно другой, причем эти два компонента друг с другом вообще никак не связаны кроме того, что находятся в одном процессе. В .NET подобное придумать теоретически тоже можно, но это очень редко. На моей памяти такое было только раз, когда в пул потоков отдавался поток с незакрытым TransactionScope. Но опять таки подобные ошибки ищутся гораздо проще благодаря доступности всех метаданных во время отладки. В частности, благодаря наличию метаданных твоя ошибка ищется очень просто: в windbg ты можешь сдампить все объекты интересующиего тебя типа, посмотреть их количество, и проверить все ссылки, кто на что ссылается. В частности, как только тестировщик видит, что приложение падает (из-за нарушения контракта), либо работает некорректно, то он делает дамп, отдает его тебе, ты видишь, что объектов два вместо одного, кричишь WTF, смотришь на код, который их создает и видишь, что этот код ломается в случае параллельного доступа. Все просто и скучно, никакого веселья и гадания на кофейной гуще, как в С++.
ГВ>Потом, например, параллельный доступ к тому же Dictionary может привести к весьма загадочным ситуациям (по этому поводу тут Klatu как-то возмущался). А поиски причин могут быть очень нетривиальными, в особенности, если этот Dictionary уедет ещё куда-то.
Эти загадочные сидуации будут касаться только кода, связанного с этим Dictionary. Уши при этом у тебя не отвалятся. А в С++ возможно все.
T>>2) Наличие коллстеков у всех исключений.
ГВ>Не надо преувеличивать: сам по себе коллстек показывает лишь на место возникновения сбоя, но ничего не говорит о той цепи причин, которые привели к его возникновению (кроме непосредственной). Об этом было говорено-переговорено лет семь-восемь назад.
В 90% случаев этого достаточно. В С++ нет даже этого. Ты просто знаешь, что что-то где-то сломалось. Что и где — неизвестно. Если не удалось поймать дамп в момент падения, то начинается веселье.
T>>3) Типобезопасность — отсутствие возможности неправильно интерпретировать память или интерфейсы.
ГВ>Ещё раз повторяю для дотнетчиков: ошибки типобезопасности вычисляются и лечатся на раз. Во-первых, потому что они на самом деле встречаются нечасто; во-вторых, потому что быстро себя проявляют; а в третьих — места, где играются с приведением типов, как правило, хорошо известны и на них в случае чего напрыгивают с проверками в первую очередь (вычурные конструкции вроде reinterpret_cast придуманы не с бухты-барахты).
Ситуация из недавней практики: поскольку проект очень большой, то его части собираются в разное время (чтобы оптимизировать время сборки). Однажды произошла такая ситуация, когда версия хедеров перестала соответствовать бинарям (забыли пересобрать). И продукт при этом работал практически всегда, но иногда в очень редких кейзах начинал течь. Сил угрохали на поиск в коде бага море. А в .NET такое невозможно в принципе.
ГВ>Так что, всё, что ты перечислил — оно, конечно, правильно, но практика — вещь такая...
Все, что я перечислял касается именно практики по интеграции большого количества unmanaged кода, написанного разными командами с большим количеством managed кода.
Здравствуйте, vdimas, Вы писали:
V>Она встречается на несколько порядков чаще в дотнете, да и в нейтиве тоже, чем проходы по памяти.
ну это просто вранье или полная некомпетентность
V>то программисты C# допускают намного больше ошибок, чем программисты на C++
Я пока что не встречал более пафосных говнокодеров, чем на С++. Вот это — точно медицинский факт. Каждое нубло, которое накропало пару примитивных программок на С++ — уже считает себя гуру