Здравствуйте, jazzer, Вы писали:
J>Потому что действительно, если ты разрабатываешь проект и глубоко его знаешь, ты знаешь, где у тебя какие указатели, где память выделяется и где и как ее можно уничтожать.
См. вторую часть условия... хотя там надо было написать "или", а не "и".
А вообще, это принципиально неправильный подход. Проект нужно строить с таким расчетом, чтобы знание его архитектуры до последней функции не являлось обязательным условием для исправления кода.
J>Если же, наоборот, тебя бросают в горячий проект быстро сделать какой-либо фикс в существующем коде, то вероятность того, что тебе потребуется при таком фиксе удалить пришедший извне указатель при условии того, что в функции, которую ты меняешь, этот указатель не удаляется — 1%.
Это очень даже немаленький процент.
J>А то ведь так можно и удалить статическую или стековую переменную, не то что деструктор не проверить...
Если в функции болтается неконстантный указатель на стековую переменную, который пришел откуда-то из другого места — то автора сего опуса надо долго и больно бить по голове.
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, jazzer, Вы писали:
J>>Потому что действительно, если ты разрабатываешь проект и глубоко его знаешь, ты знаешь, где у тебя какие указатели, где память выделяется и где и как ее можно уничтожать.
Д>См. вторую часть условия... хотя там надо было написать "или", а не "и".
да, конечно же, или
Д>А вообще, это принципиально неправильный подход. Проект нужно строить с таким расчетом, чтобы знание его архитектуры до последней функции не являлось обязательным условием для исправления кода.
А где я утверждал обратное и говорил, что проекты надо строить иначе?
Наоборот, весь мой последующий текст является аргументом в пользу этого твоего тезиса.
J>>Если же, наоборот, тебя бросают в горячий проект быстро сделать какой-либо фикс в существующем коде, то вероятность того, что тебе потребуется при таком фиксе удалить пришедший извне указатель при условии того, что в функции, которую ты меняешь, этот указатель не удаляется — 1%.
Д>Это очень даже немаленький процент.
Серьезно? Для чего же он "очень даже немаленький"?
Он достаточно маленький для того, чтобы приложить "все усилия для выяснения происхождения этого указателя".
J>>А то ведь так можно и удалить статическую или стековую переменную, не то что деструктор не проверить...
Д>Если в функции болтается неконстантный указатель на стековую переменную, который пришел откуда-то из другого места — то автора сего опуса надо долго и больно бить по голове.
Не спорю. Но ведь если у тебя есть функция, в которую ты должен внести изменения, в которую прилетел указатель, и в ней он раньше не удалялся, зачем тебе его удалять? А если и понадобилось (тот самый один случай из ста) — разве ты не приложишь усилия, чтобы выяснить его происхождение? Более того, ты их наверняка уже приложит, раз пришел к выводу, что его надо удалять именно здесь.
Таким образом, эта ошибка возможна только в результате КРАЙНЕЙ безалаберности разработчика, который просто стреляет во все, что движется.
Здравствуйте, jazzer, Вы писали:
J>Он достаточно маленький для того, чтобы приложить "все усилия для выяснения происхождения этого указателя".
В спешке и не про такое забудешь.
J>Не спорю. Но ведь если у тебя есть функция, в которую ты должен внести изменения, в которую прилетел указатель, и в ней он раньше не удалялся, зачем тебе его удалять?
Скорее — наоборот. "Некто" передаст указатель на твой базовый класс в функцию, которая по каким-то причинам полиморфно уничтожает объекты — и все, кирдык.
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, jazzer, Вы писали:
J>>Он достаточно маленький для того, чтобы приложить "все усилия для выяснения происхождения этого указателя".
Д>В спешке и не про такое забудешь.
Э-э-э...
Без комментариев
J>>Не спорю. Но ведь если у тебя есть функция, в которую ты должен внести изменения, в которую прилетел указатель, и в ней он раньше не удалялся, зачем тебе его удалять?
Д>Скорее — наоборот. "Некто" передаст указатель на твой базовый класс в функцию, которая по каким-то причинам полиморфно уничтожает объекты — и все, кирдык.
Ну да, особенно если эта функция называется как-нибудь безобидно, типа dump_to_cerr
Here, I describe the more innovative and powerful mechanism for overloading whitespace. Consider x*y.
In programming languages (e.g. Fortran, Pascal, and C++), this is the conventional notation for
multiplying two values. However, mathematicians and physicists traditionally do not use the operator *.
Instead they use simple juxtaposition to indicate multiplication. That is, for variables x and y of suitable
types,
x y
means multiply x by y.
This is simply achieved by overloading the space operator for double-precision floating-point values:
Given one of these definitions, a physicist can use his (or her) conventional notation rather than the
notation that has become conventional among computer scientists:
double f(double x, double y, double z)
{
return a + x y pow z; // using also a user-defined operator pow
}
Clearly, the space operator has (by default) a precedence lower than pow and higher than +. The
mechanism for assigning precedence to user-defined operators is described in detail in the companion
article.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Д>I talked to John Lykos at one of the conferences, and he told me that he would pay big bucks for a tool that would be able to tell what header files must be included in a given file.
Д>
Д>Когда я занимался портированием прог, я мечтал о таком инструменте каждый день
ага, и сразу модульности можно сказать ДАЗВИДАНЬЯ
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, jazzer, Вы писали:
J>>За минус спасибо, конечно, а аргументы будут?
Д>
Д>class A
Д> {
Д> };
Д>class B : public A
Д> {
Д> }
Д>B * pb = new B;
Д>A * pa = pb; // пытаются заменить на A * pa = (A *)pb;, что ИМХО никому не нужно
Д>delete pb; // а то сейчас опять про меморилик вспомнят :)
Д>
Д>В один "прекрасный" день кто-нибудь другой (или ты сам) напишет delete pa; вместо delete pb; Д>В данном случае это маловероятно, конечно. А вот если создание объекта и его удаление будут разнесены в разные места проги — запросто. Д>Wish you happy debugging Д>Только не надо кричать "да я! да я никогда!" и бить себя пяткой в грудь. Все когда-нибудь ошибаются...
Вопрос не в том, ошибаются ли люди или нет, а как часто. Проблема, упомянутая выше, надуманая. Так же как и многие другие "проблемы", возникающие при использовании указателей.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, VladD2, Вы писали:
VD>>Ведь по хорошему такой код не должен был бы скомпилироваться без наличия виртуального деструктора.
J>Это по какому это хорошему мне запрещается создавать неполиморфные иерархии без виртуального деструктора? J>Вот спасибо...
Запрещаться должна ваозможность вызова неверного деструктора. В С++ она не только не запрещается, но и поощьряется, так как виртуальный деструктор по умолчанию отсуствует. Я бы еще понял, если бы программист намеренно приказывал компилятору не создавать виртуальный деструктор, а так... багодром и постоянное держание в голове кучи ненужных подробностей.
... << RSDN@Home 1.1.4 beta 3 rev. 267>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, jazzer, Вы писали:
J>Прошу прощения, но это аргумент из серии "Давайте запретим пользоваться указателями, потому что рано или поздно кто-нть поломает память, потому что все когда-нибудь ошибаются".
Очень дельное предложение. Если и не запретить, то ограничить точно нужно. И желательно надежно ограничить, а не на уровне паттерна.
J>Я действительно никогда не писал ничего не удалял таким образом. J>Единственный случай, когда ко мне приходит указатель на базовый класс, который я должен удалить — это когда этот указатель вернулся из фабрики полиморфных объектов,
Долеко не единственный. Ты видимо просто повезло и ты редко встречался с подобными вещами.
J> но в таком случае все и так полиморфное.
Тоже не факт. Особенно если код пишут много человек.
... << RSDN@Home 1.1.4 beta 3 rev. 267>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinclair, Вы писали:
S>А что, есть какие-то возражения против этого аргумента? Пока что среды, запретившие пользоваться указателями, демонстрируют сплошные преимущества и никаких недостатков.
Скажем так, не запрещающие, а ограничивающие. В такой формулировке — полностью согласен.
... << RSDN@Home 1.1.4 beta 3 rev. 267>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, jazzer, Вы писали:
J>>За минус спасибо, конечно, а аргументы будут?
Д>
Д>class A
Д> {
Д> };
Д>class B : public A
Д> {
Д> }
Д>B * pb = new B;
Д>A * pa = pb; // пытаются заменить на A * pa = (A *)pb;, что ИМХО никому не нужно
Д>delete pb; // а то сейчас опять про меморилик вспомнят :)
Д>
Д>В один "прекрасный" день кто-нибудь другой (или ты сам) напишет delete pa; вместо delete pb; Д>В данном случае это маловероятно, конечно. А вот если создание объекта и его удаление будут разнесены в разные места проги — запросто. Д>Wish you happy debugging Д>Только не надо кричать "да я! да я никогда!" и бить себя пяткой в грудь. Все когда-нибудь ошибаются...
Ошибка произошла гораздо раньше в строке "class B : public A". Квалифицированный программист должен задать себе пару вопросов перед тем, как сделать подобное:
1) класс A непредназначен для полиморфного использования, хочу ли я от него унаследовать?
2) решит ли мою задачу агрегирование или на худший случай закрытое наследование?
Ошибка данного типа не является ошибкой из серии "ах, опять оплошал!" Она не допускается случайно. Наоборот, это сознательное действие, объяснимое только отсутствием необходимой квалификации.
PS.:
удивительный факт:
shared_ptr< A > a( new B() );
отработает нормально даже при отсутствии виртуального деструктора.
Здравствуйте, jazzer, Вы писали:
J>Э-э-э... J>Без комментариев
А какие там комментарии. В исходниках FileZilla было место, где один указатель на объект освобождается два раза в разных местах. Не уверен, что сейчас это исправлено. А ты говоришь — тип деструктора каждый раз проверять
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, jazzer, Вы писали:
J>>Э-э-э... J>>Без комментариев
Д>А какие там комментарии. В исходниках FileZilla было место, где один указатель на объект освобождается два раза в разных местах. Не уверен, что сейчас это исправлено. А ты говоришь — тип деструктора каждый раз проверять
Честно говоря, я не знаю, что такое FileZilla и что же там была за спешка такая, что народ пишет такую лажу.
Подозреваю, что это опенсорсный проект, если это так — то неудивительно, потому что половина опенсорсного софта, который я видел, написана какими-то студентами-недоучками от излишка свободного времени.
Естественно, что ни о какой культуре программирования в таком случае речи нет.
И естественно, что для них же лучше использовать какие-нть инструменты попроще, типа java или C#.
Спешка — это не аргумент для написания непродуманного кода.
Я никогда не говорил, что на С++ писать очень просто.
Тем не менее, я продолжаю утверждать, что все проблемы, которые, как утверждается, похоронят С++, упираются просто в недостаток квалификации программиста.
Каждый язык подразумевает какие-то идиомы, которые программист должен знать.
В С++ надо следить за указателями, в java надо использовать стринг-буферы, а не строки, и т.д.
Да, идиомы С++ сложнее, чем в java, ну и что с того?
И те, и другие вполне подвластны человеку с высшим образованием.
Если человек знает язык и его идиомы — для него никаких проблем на этом языке писать и избегать всех этих "страшных и неразрешимых проблем" не составит.
Здравствуйте, jazzer, Вы писали:
J>Подозреваю, что это опенсорсный проект, если это так — то неудивительно, потому что половина опенсорсного софта, который я видел, написана какими-то студентами-недоучками от излишка свободного времени.
Он и правда опен-сорсный, но это еще ни о чем не говорит. Закрытый код ничем не лучше, а зачастую еще и намного хуже. Достаточно посмотреть на список уязвимостей современного софта.
Я не видел еще ни одной действительно сложной программы на С++, которая была бы хорошо спроектирована и реализована.
J>Спешка — это не аргумент для написания непродуманного кода.
А увеличение срока разработки в разы из-за "продумывания кода" — это не аргумент для заказчика.
J>Тем не менее, я продолжаю утверждать, что все проблемы, которые, как утверждается, похоронят С++, упираются просто в недостаток квалификации программиста.
Квалификация программиста нужна не для борьбы с граблями языка, а для анализа предметной области и проектирования системы. Если язык этому мешает — надо искать другой язык. Точка.
Правильно тут было сказано — или ты делаешь полиморфную иерархию, или не-полиморфную. Значит — или ты делаешь виртуальный деструктор, или делаешь наследование закрытым (еще лучше — агрегируешь объект). Уродцы наподобие открытого наследования без виртуального дестркутора не должны иметь права на существование.
J>И те, и другие вполне подвластны человеку с высшим образованием.
Научиться говорить на китайском языке тоже вполне доступно человеку с высшим образованием. Другой вопрос — а нужно ли оно ему?
J>Если человек знает язык и его идиомы — для него никаких проблем на этом языке писать и избегать всех этих "страшных и неразрешимых проблем" не составит.
Давай попробуем уточнить. Вот ты сам как считаешь — ты знаешь все идиомы, нужные для работы с C++?
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, jazzer, Вы писали:
J>>Подозреваю, что это опенсорсный проект, если это так — то неудивительно, потому что половина опенсорсного софта, который я видел, написана какими-то студентами-недоучками от излишка свободного времени.
Д>Он и правда опен-сорсный, но это еще ни о чем не говорит. Закрытый код ничем не лучше, а зачастую еще и намного хуже. Достаточно посмотреть на список уязвимостей современного софта.
закрытый код пишется небольшим количеством людей с предсказуемой квалификацией.
Для опенсорсного проекта нужен очень грамотный ПМ, который сможет разбираться во всех присылаемых патчах и коммитах, отсеивать некачественное, по возможности исправлять, и т.д.
С опен-сорсом работы выше крыши.
Д>Я не видел еще ни одной действительно сложной программы на С++, которая была бы хорошо спроектирована и реализована.
что ты называешь "действительно сложным"?
J>>Спешка — это не аргумент для написания непродуманного кода.
Д>А увеличение срока разработки в разы из-за "продумывания кода" — это не аргумент для заказчика.
Еще раз. Случаи внесения изменений, когда требуется "продумывать код", возникают один раз из ста.
Из-за этого сроки в разы не увеличиваются.
К тому же, если не гоняться за оптимизацией в случае действительно спешки, можно писать проще и использовать более безопасные конструкции.
В большинстве случаев (если это не сервер) можно просто создать меморилик — он все равно сдохнет, когда программу опустят.
А когда будет время — разобраться и перепроектировать.
J>>Тем не менее, я продолжаю утверждать, что все проблемы, которые, как утверждается, похоронят С++, упираются просто в недостаток квалификации программиста.
Д>Квалификация программиста нужна не для борьбы с граблями языка, а для анализа предметной области и проектирования системы. Если язык этому мешает — надо искать другой язык. Точка.
Мне язык не мешает. И большинству тут присутствующих — тоже.
Те, кому мешает, ушли в java/C# — ради бога, я далек от религиозных войн и не перестану из-за этого с ними здороваться.
Д>Правильно тут было сказано — или ты делаешь полиморфную иерархию, или не-полиморфную. Значит — или ты делаешь виртуальный деструктор, или делаешь наследование закрытым (еще лучше — агрегируешь объект). Уродцы наподобие открытого наследования без виртуального дестркутора не должны иметь права на существование.
Не согласен. С++, как тут было сказано много раз, поддерживает множество парадигм программирования. И на ООП с динамической типизацией, вируальностями и фабриками свет клином не сошелся. Посмотри на STL — там сплошь наследование без виртуальностей.
J>>И те, и другие вполне подвластны человеку с высшим образованием.
Д>Научиться говорить на китайском языке тоже вполне доступно человеку с высшим образованием. Другой вопрос — а нужно ли оно ему?
Вопрос, чему учить студентов, обсуждается у нас в другой ветке.
Здесь же разговаривают люди, которые уже знают китайский, вовсю им пользуются и зарабатывают им деньги, так что обсуждать с ними этот вопрос абсурдно.
J>>Если человек знает язык и его идиомы — для него никаких проблем на этом языке писать и избегать всех этих "страшных и неразрешимых проблем" не составит.
Д>Давай попробуем уточнить. Вот ты сам как считаешь — ты знаешь все идиомы, нужные для работы с C++?
Нельзя объять необъятное.
Я знаю достаточно идиом, чтобы быстро и легко писать безопасный код.
Hello, Дарней!
You wrote on Thu, 23 Dec 2004 09:01:57 GMT:
Д> Квалификация программиста нужна не для борьбы с граблями языка, а для Д> анализа предметной области и проектирования системы. Если язык этому Д> мешает — надо искать другой язык. Точка. Правильно тут было сказано - Д> или ты делаешь полиморфную иерархию, или не-полиморфную.
Полиморфизм разный бывает. Например, может понадобится, чтобы объекты
SheetDrawer наследовались от Rectange просто для того, чтобы их коллекцию
можно было скормить функции, умеющей как-то упорядочивать прямоугольники.
При этом храняться они в программе именно как SheetDrawer'ы и удалять их как
Rectange'ы никто и никогда не собирается.
Д> Значит — или ты делаешь виртуальный деструктор, или делаешь наследование Д> закрытым (еще лучше — агрегируешь объект). Уродцы наподобие открытого Д> наследования без виртуального дестркутора не должны иметь права на Д> существование.
Эти "уродцы" очень нужны в одном вполне конкретном случае — для повторного
использования имлементации какой-либо функциональности. Закрытое
наследование тут не годится, агрегация — куча ручной работы, если интерфейс
базового класса объемен. Виртуальный деструктор — напрасный перерасход
памяти. Вполне приемлемым решением является protected деструктор в базовом
классе. И не надо навешивать ярлыки и клеймить что попало.
With best regards, Sergey.
Posted via RSDN NNTP Server 1.9 delta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, jazzer, Вы писали:
J>Для опенсорсного проекта нужен очень грамотный ПМ, который сможет разбираться во всех присылаемых патчах и коммитах, отсеивать некачественное, по возможности исправлять, и т.д.
Для закрытого проекта он нужен ничуть не меньше. Чтобы общаться с заказчиком, который никогда не знает сам, что ему нужно. Чтобы перепроектировать программу, когда заказчику вместо кофемолки вдруг понадобится газонокосилка. Чтобы объяснять разработчикам, что объяснения типа "но у меня же это работает!" еще не доказывают, что гнилой код не надо переписывать.
J>что ты называешь "действительно сложным"?
Программу, которая не является очередной системой для автоматизации какого-нибудь третьего заборостроительного завода.
J>Еще раз. Случаи внесения изменений, когда требуется "продумывать код", возникают один раз из ста.
Еще раз. В программы не только вносят изменения, их перед этим еще и пишут с нуля.
J>Мне язык не мешает. И большинству тут присутствующих — тоже.
Достаточно заглянуть в форум по С++, чтобы убедиться, что большинству он таки мешает. А если заглянуть в код какого-нибудь проекта, так и вовсе волосы дыбом встают. Порой просто диву даешься, как же оно вообще работает. Если твой проект не такой — значит, это очень редкое исключение.
J>Не согласен. С++, как тут было сказано много раз, поддерживает множество парадигм программирования. И на ООП с динамической типизацией, вируальностями и фабриками свет клином не сошелся. Посмотри на STL — там сплошь наследование без виртуальностей.
где, например?
J>Здесь же разговаривают люди, которые уже знают китайский, вовсю им пользуются и зарабатывают им деньги, так что обсуждать с ними этот вопрос абсурдно.
Я подозревал, что в конце концов наше обсуждение выродится в утверждения вида "а если не понимаешь С++, то вообще ты сам дурак"
Очень неприятно, что так и произошло.
J>Я знаю достаточно идиом, чтобы быстро и легко писать безопасный код.
Все так думают, пока не приходит пора копнуть на пару метров от того места, где они привыкли копать.
Hello, Дарней!
You wrote on Thu, 23 Dec 2004 10:34:10 GMT:
S>> Виртуальный деструктор — напрасный перерасход памяти.
Д> Как ты думаешь — сколько процентов памяти ты сэкономишь в типичном Д> проекте таким образом?
Я не в курсе, что такое типичный проект — как-то ни разу не писал код для
типичных проектов, все сплошь какая-то конкретика попадается. В одном
конкретном случае таким образом около 5% памяти набегало. По быстродействию
трудно без профилирования оценить, но инициализация таблиц виртуальных
функций (которые часто нафиг не нужны) тоже не бесплатная.
With best regards, Sergey.
Posted via RSDN NNTP Server 1.9 delta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.