Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.137.171.121] |
|
Сообщ.
#1
,
|
|
|
Вобщем тема для пользователей исключительно Цэ++
Регламент 1) Спорим обо все, что касается или должно касаться Цэ++ 2) Любые темы сводим к возможностям Цэ++ 3) Если модератор "снесет" тему из раздела Цэ++, ожидайте наплыв прогеров на васике. Лично я забью на нее. Ожидаемый профит Что и как обсуждаемое можно реализовать средствами Цэ++, что можно и нужно заменить "своими"средствами. Ньюбы, типа меня, поучаться. Профи смогут реализовать интересные идеи в жысть. Одна просьба к модерам, пресекать терки типа: - ты прогаешь на Цэ++? - нет, пока только на ассемблере - фуууу!!! как это низко ... ну естественно, если тема улетит в "корзину", внезапно пойму, возможности - такие возможности Для затравочки ... контрактное программирование В языке D это - не библиотечная часть языка. Это часть языка. Суть. Функция и метод класса могут "обещать" предсказуемое поведение на входе и выходе. В случае наследования контракты работают по принципу "или". Иными словами, если контракт базового класса не выполняется - начинает обсчитываться контракт производного класса. Из книжки Александреску: Цитата Другими словами, in-контракты комбинируются с использованием дизъюнкции в сочетании с коротким замыканием: точно один контракт должен выполниться, и контракт предка пробуется первым. Таким образом, исключается вероятность того, что контракт потомка труднее удовлетворить, чем контракт предка. С другой стороны, потомок предоставляет второй шанс пройти тест предусловия, не пройденный в первый раз. Язык Цэ++, равно как и язык D, требует "базы" - соответствия типов. Это можно считать "контрактом" высшего порядка. Далее более Ваше отношение? Будете ли вы в продакшен-коде оставлять assert-ы? Считаете ли нужным генерировать исключения а-ля ExceptionAssertIn или ExceptionAssertOut? |
Сообщ.
#2
,
|
|
|
Тема не конкретна, базара ожидается много всякого; прошу сразу двинуть сие в холивары.
|
Сообщ.
#3
,
|
|
|
Так и знал. Но надеялся
|
Сообщ.
#4
,
|
|
|
Цитата JoeUser @ Я их вообще не использую и не советую. assert() суть тяжёлое наследие детства C/C++.Будете ли вы в продакшен-коде оставлять assert-ы? M P.S. Славян, для меня желание ТС важнее, если оно не противоречит Правилам. В холивары тема переедет, если вы все в совокупности, не исключая ТС, сделаете её неудовлетворяющей Правилам. К тому же я вижу основной недостаток холиваров в том, что там не требуется тематики. JoeUser же рассчитывает на тематический спор, посему флуда попрошу воздерживаться. В целом не вижу причин не оставить пока тему здесь. |
Сообщ.
#5
,
|
|
|
Цитата Qraizer @ Понеслась! Чем вам не нравятся ассерты? Для обрабатываемых ошибок - используем исключения, для необрабатываемых - ассерты. Я их вообще не использую и не советую. assert() суть тяжёлое наследие детства C/C++. |
Сообщ.
#6
,
|
|
|
applegame, а почему для всего не использовать исключения?
Добавлено JoeUser, контракты даже предлагали включить в C++. В плане теории можно прочесть о них у Бертрана Майера, он придумал Design by contract. Но идёт все это от т.н. "троек" Хоара, чёрт знает когда описанных |
Сообщ.
#7
,
|
|
|
applegame, как бы так покороче... исключения как раз для необрабатываемых, а обрабатываемые и так обработаны.
|
Сообщ.
#8
,
|
|
|
Цитата D_KEY @ JoeUser, контракты даже предлагали включить в C++. В плане теории можно прочесть о них у Бертрана Майера, он придумал Design by contract. Но идёт все это от т.н. "троек" Хоара, чёрт знает когда описанных Пасип, бегло почитал - чуйка не подвела. По факту раздувание кода встроенными типа "тестами". Для режима отладки ниче-так, но если это все барахло останется и в продакшене, лично я строго против. Добавлено Предлагаю следующую тему "множественное наследование vs примеси" Плюсы, минусы .... |
Сообщ.
#9
,
|
|
|
Цитата Qraizer @ applegame, как бы так покороче... исключения как раз для необрабатываемых, а обрабатываемые и так обработаны. Ни разу не согласен. Для чего придумали блок кэтч? Для последующей ловли, и возможно корректной обработки исключительной ситуации, как следствие - возможного нормального исполнения программы. Ассерты же - это финиш с посмертным выбросом инфы. Так что, скорее наоборот. |
Сообщ.
#10
,
|
|
|
Цитата JoeUser @ Кто тебе мешает ассерт поймать? Ассерты же - это финиш с посмертным выбросом инфы. |
Сообщ.
#11
,
|
|
|
Цитата amk @ Цитата JoeUser @ Кто тебе мешает ассерт поймать?Ассерты же - это финиш с посмертным выбросом инфы. Это как, и главное зачем? |
Сообщ.
#12
,
|
|
|
Цитата JoeUser @ Да тем же catch'ем. Насколько помню, accept в C++ просто генерирует исключение. которое, как и любое другое можно перехватить и обработать.Это как, и главное зачем? А зачем? Так это тебе самому виднее, зачем тебе отладочную проверку перехватывать захотелось. Кстати, в релизе accept'ы не компилируются. |
Сообщ.
#13
,
|
|
|
Цитата amk @ Зачем его ловить? Ассерт следует использовать в случаях, когда возникла ошибка, которую невозможно обработать, кроме как написать предсмертную записку (в моей смерти прошу винить того-то) и совершить сепукку.Кто тебе мешает ассерт поймать? Цитата D_KEY @ Можно, конечно, и исключения использовать, но мне такой подход не нравится. Объясню на реальном примере.applegame, а почему для всего не использовать исключения? У меня в проекте с некоторой периодичностью происходит обновление неких метаданных предоставлямых третьей стороной в виде JSON-а по протоколу HTTPS. Эта третья сторона имеет дурную привычку иногда выдавать 503 ошибку или вместо JSON-а отдавать пустую страницу или внезапно в JSON-е обнаруживаются какие-то новые поля или исчезают старые. Обновление метаданных не критично, желательно, но можно и со старыми продолжать успешно работать. У меня это все завернуто в один блок try/catch, ловящий все исключения (а там их может быть несколько видов), так как мне совсем не принципиально почему обломилось обновление, то-ли HTTP-ошибки, то ли JSON-кривой или вовсе обрыв соединения. Во всех случаях информация об ошибке пишется в лог, а приложение продолжает работать как обычно. Но в том же блоке есть несколько инвариантов, которые обрабатываются именно ассертами с падением. Сначала приложение гоняется в дебаг-версии, отлавиливаются и исправляются все ассерты, после чего делаем релиз из которого уже ненужные ассерты автоматически выбрасываются. ИМХО, удобно. |
Сообщ.
#14
,
|
|
|
Ассерты нужны для тех случаев, которые в теории никогда не должны случаться, а если все-таки случились, то это 100% баг в коде и надо крэшиться с дампом. Например:
class vector { ... item& operator[](size_t index) { assert((index < m_itemCount) && "Invalid index"); return m_items[index]; } }; |
Сообщ.
#15
,
|
|
|
Цитата Pacific @ Ну совсем крэшиться, полагаю нехорошо. Надо бы перехватить, выдать вменяемое сообщение для конечного пользователя и культурно завершиться.Ассерты нужны для тех случаев, которые в теории никогда не должны случаться, а если все-таки случились, то это 100% баг в коде и надо крэшиться с дампом. Конкретно в моем случае можно крэшиться, так как конечный пользователь - это я сам |
Сообщ.
#16
,
|
|
|
applegame, заведи особый вид исключений и все... Кстати, никогда не ловил в релизе баги, которые происходили потому, что там раньше был assert, а теперь просто ничего?
|
Сообщ.
#17
,
|
|
|
Цитата amk @ Да тем же catch'ем. Согласно описалову - никаких исключений: Цитата The definition of the macro assert depends on another macro, NDEBUG, which is not defined by the standard library. If NDEBUG is defined as a macro name at the point in the source code where <cassert> is included, then assert does nothing. If NDEBUG is not defined, then assert checks if its argument (which must have scalar type) compares equal to zero. If it does, assert outputs implementation-specific diagnostic information on the standard error output and calls std::abort. The diagnostic information is required to include the text of expression, as well as the values of the standard macros __FILE__, __LINE__, and the standard variable __func__. А std::abort, в свою очередь - noexcept. Да и вообще, если бы и было возможно - странный, мягко сказать механизм был бы. Исключениями возможно половить ситуации, которые возможно предусмотреть. На непредусмотренное (или неподлежащее исправлению) - выкинуть посмертно сообщение и выйти. Assert, имхо, именно для этого и заточен - сообщить о неведомом баге и выйти и программы. |
Сообщ.
#18
,
|
|
|
Цитата JoeUser @ Предлагаю следующую тему "множественное наследование vs примеси" Плюсы, минусы .... Раскрой тему, в чем ты тут видишь противостояние? Тем более, что в C++ примеси можно сделать только через наследование. |
Сообщ.
#19
,
|
|
|
Цитата D_KEY @ Раскрой тему, в чем ты тут видишь противостояние? Да как-то недавно Oraizer упомянул, мол (недословно) "в Цэ++ уже давно есть множественное наследование, а в таких языках как Джава и .NET их нет, и Цэ++ молодец, да!" Ну а я вот почитываю описание языка D - там похоже все нужное от множественного наследования решается примесями, полностью. Пока возникает вопрос: а нужно ли вообще множественное наследование (тому же D), если реализовали полноценные примеси? |
Сообщ.
#20
,
|
|
|
Цитата JoeUser @ Пока возникает вопрос: а нужно ли вообще множественное наследование (тому же D), если реализовали полноценные примеси? А зачем нужны примеси, если есть множественное наследование? Зачем плодить сущности? |
Сообщ.
#21
,
|
|
|
Цитата D_KEY @ А зачем нужны примеси, если есть множественное наследование? Зачем плодить сущности? Еще толком не разобрался, но беглое чтение пока убеждает - что примеси более гибки. Надо попробовать сравнить примеры-реализации. Пока только впечатление. |
Сообщ.
#22
,
|
|
|
Почитал повнимательнее - даж и не знаю как сравнивать. Не совсем сравниваемое получается. Описание из книги Александреску:
Цитата Короче говоря, выражение mixin позволяет вам превратить строку в исполняемый код. Синтаксис выражения выглядит как mixin(выражение), где выражение должно быть строкой, известной во время компиляции. Это ограничение исключает возможность динамически создавать программный код, например читать строку с терминала и интерпретировать ее. Нет, D - не интерпретируемый язык, и его компилятор не является частью средств стандартной библиотеки времени исполнения. Хорошие новости заключаются в том, что D на самом деле запускает полноценный интерпретатор во врем я компиляции, а значит, вы можете собирать строки настолько изощренными способами, насколько этого требуют условия вашей задачи. На примерах: Подмешивание виртуальной функции в класс mixin template Foo() { void func() { writeln("Foo.func()"); } } class Bar { mixin Foo; } class Code : Bar { override void func() { writeln("Code.func()"); } } void test() { Bar b = new Bar(); b.func(); // calls Foo.func() b = new Code(); b.func(); // calls Code.func() } А тут генерация перегрузок операторов + - ^ ++ -- с помощю предварительной интерпретации кода перед компиляцией: struct CheckedInt(N) if (isIntegral!N) { private N value; this(N value) { this.value = value; } CheckedInt opUnary(string op)() if (op == "+" || op == "-" || op == "^") { return CheckedInt(mixin(op ^ "value")); } ref CheckedInt opUnary(string op)() if (op == "++" || op == "--" ) { enum limit = op == "++" ? N.max : N.min; enforce(value != limit); mixin(op ^ "value;"); return this; } } Как можно для одного оператора "==" такое похожее сделать в Цэ++ template <typename T> struct AddNoEq { virtual bool operator==(const T &cmp) const = 0; bool operator!=(const T &cmp) const { return !static_cast<const T*>(this)->operator== (cmp); } }; Непривычная хрень - примеси, но впечатляет. Надо разбираться. |
Сообщ.
#23
,
|
|
|
Цитата D_KEY @ Зачем, если уже есть особый вид "исключений" - assert. Если ты опасаешься, что не все еще отлажено, можешь не убирать ассерты в релизе. applegame, заведи особый вид исключений и все... Кстати, никогда не ловил в релизе баги, которые происходили потому, что там раньше был assert, а теперь просто ничего? Добавлено Цитата JoeUser @ Именно так.Почитал повнимательнее - даж и не знаю как сравнивать. Не совсем сравниваемое получается. Примеси и наследование пересекаются кое-где, но это разные сущности. Подмешивание примеси A в класс B добавляет функциональности, но не добавляет полиморфизма: класс B не стал класом A. Зачастую множественное наследование можно заменить примесями, но таки это не одно и тоже. Не забываем также, что в D разрешено множественное наследование интерфейсов. Что касается цитаты Александреску, то там описаны строковые миксины. Есть еще обычные миксины: mixin template Foo(T) { void test(T)(T arg) {} } class Bar { mixin Foo!int; // все что было описано внутри Foo будет здесь, но контекст остается местный } ... Bar bar = new Bar; bar.test(10); Но это выходит за рамки холивора, в C++ нет примесей, ни строковых ни обычных. |
Сообщ.
#24
,
|
|
|
Цитата applegame @ Цитата D_KEY @ Зачем, если уже есть особый вид "исключений" - assert. Если ты опасаешься, что не все еще отлажено, можешь не убирать ассерты в релизе.applegame, заведи особый вид исключений и все... Кстати, никогда не ловил в релизе баги, которые происходили потому, что там раньше был assert, а теперь просто ничего? assert - это не вид исключений, а отдельный механизм. |
Сообщ.
#25
,
|
|
|
Цитата JoeUser @ Я строковые миксины не очень люблю. Они крайне мощные, но трудночитаемы. В некоторых случаях они позволяют фокусы вроде автоматической генерации необходимого кода, что совместно со статической рефлексией превращается в весьма мощный инструмент. Непривычная хрень - примеси, но впечатляет. Надо разбираться. Добавлено Цитата D_KEY @ Чо, правда??? Ты кавычки вокруг слова "исключение", нарочно не заметил? assert - это не вид исключений, а отдельный механизм. оффтоп о D В D ассерты - это особый вид исключений, настоящих исключений, можно поймать c помощью catch если нужно. |
Сообщ.
#26
,
|
|
|
Цитата applegame @ Но это выходит за рамки холивора, в C++ нет примесей, ни строковых ни обычных. Совсем не выходит! Мы же говорим о языках, об способах, возможностях, а не х3 о чем. Это как раз таки, имхо, нормальная тематика. Все ровно. Добавлено Цитата applegame @ но не добавляет полиморфизма Ты хотел сказать "инкапсуляции"? Перегрузка виртуальных функций как-раз таки добавляет полиморфизм. |
Сообщ.
#27
,
|
|
|
Цитата JoeUser @ Для разговоров о D и сравнения с С++ уже есть холивор - D vs C++ Надо признать, местами D меня выбешивает, в нем полно всяких неочевидных и раздражающих моментов. Я даже одно время порывался пару раз бросить D и вернуться на корявенькие, но очень хорошо формализованые и хорошо вылизанные (в отличие от D) плюсы. Но меня сразу начинало тошнить от ужасного синтаксиса шаблонов и общей слабости метапрограммирования в плюсах. Потом я успокаивался, багу исправляли в следующем релизе, и все становилось на свои места. Совсем не выходит! Мы же говорим о языках, об способах, возможностях, а не х3 о чем. Это как раз таки, имхо, нормальная тематика. Все ровно. |
Сообщ.
#28
,
|
|
|
applegame, а при чем тут D?
|
Сообщ.
#29
,
|
|
|
Цитата applegame @ D vs C++ Ясн. Не видел. |
Сообщ.
#30
,
|
|
|
Цитата D_KEY @ Ты издеваешься, да? Кавычки опять проигнорил, зато спросил при чем тут нечто, обернутое в спойлер и помеченое, как оффтоп. Иди потролль в другом месте. applegame, а при чем тут D? |
Сообщ.
#31
,
|
|
|
Цитата Вобщем тема для пользователей исключительно Цэ++ Регламент 1) Спорим обо все, что касается или должно касаться Цэ++ 2) Любые темы сводим к возможностям Цэ++ 3) Если модератор "снесет" тему из раздела Цэ++, ожидайте наплыв прогеров на васике. Лично я забью на нее. |
Сообщ.
#32
,
|
|
|
D_KEY, с этим я согласен. D сюда принес топикстартер. Срезать и перенести в соответствующий холивор, если Qraizerу будет не лень. Или вовсе поудалять.
|
Сообщ.
#33
,
|
|
|
А что плохого в примесях D, если есть частичная реализация в Цэ++? Что за паталогическая тяга стараться оставлять темы только типа "а как выделить память в функции?". Вам самим от этого не скушно?
Добавлено Цитата JoeUser @ Ты хотел сказать "инкапсуляции"? Кстати, инкапсуляция с помощью примесей так же - в наличии. Пруф: Скрытый текст import std.stdio; mixin template Foo() { int z = 10; void func() { writeln("Foo.func()", z); } } class Bar { mixin Foo; } class Code : Bar { override void func() { writeln("Code.func()",z); } } void main() { Bar b = new Bar(); b.func(); // calls Foo.func() b = new Code(); b.func(); // calls Code.func() <---------- печатает 10 } |
Сообщ.
#34
,
|
|
|
Цитата JoeUser @ Ничего плохого, просто как можно обсуждать примеси в контексте C++?А что плохого в примесях D, если есть частичная реализация в Цэ++? Цитата JoeUser @ Да не о инкапсуляции речь, а о полиморфизме. Вот тебе код на C++, попробуй его заменить примесями:Кстати, инкапсуляция с помощью примесей так же - в наличии. Пруф: #include <iostream> using namespace std; #include <iostream> using namespace std; class Foo {}; class Bar {}; class Poly: public Foo, public Bar {}; void func1(Foo foo) {} void func2(Bar bar) {} int main() { Poly poly; func1(poly); func2(poly); return 0; } |
Сообщ.
#35
,
|
|
|
Хотя, блин! Посыпаю голову пеплом!!! Не инкапсуляция - "наследование". Инкапсуляция в классах по факту.
|
Сообщ.
#36
,
|
|
|
Цитата applegame @ Да не о инкапсуляции речь, а о полиморфизме. Вот тебе код на C++, попробуй его заменить примесями: Понял. Осознал. Согласен. Следствие подходов языка. И примеси тут только (в определенных случаях) синтаксический сахар. А замена множественного наследования: 1) Множественное наследование интерфейсов 2) Множественное наследование подтипов Что, кстати, тоже очень даже неплохо укладывается в логику. По факту, множественное наследование - это не самоцель, а способ достижения функционала и данных наследников. А как это будет сделано - количество строк кода покажет |
Сообщ.
#37
,
|
|
|
Цитата applegame @ В том-то и прикол, что опасаться нужно всегда. Откуда уверенность, что под-assert()-ные проверки больше не потребуются никогда Зачем, если уже есть особый вид "исключений" - assert. Если ты опасаешься, что не все еще отлажено, можешь не убирать ассерты в релизе. Добавлено Цитата JoeUser @ Это лирика. Главное назначение исключений в предоставлении способа осуществления нелокальных переходов, безопасного к инвариантам. Как этот механизм будет использован программистом – это его личное дело. По ряду причин считается, что исключения должны использоваться в исключительных случаях. Под таковыми лично я вижу только (цитата из стандарта кодирования моего в частности авторства):Для чего придумали блок кэтч? Для последующей ловли, и возможно корректной обработки исключительной ситуации, как следствие - возможного нормального исполнения программы. Ассерты же - это финиш с посмертным выбросом инфы. Цитата Это не догма, конечно, однако нетрудно видеть, что этими случаями исчерпываются все возможные случаи, когда без исключений не обойтись. Внезапно выясняется, что assert()-ы прекрасно подходят под первый случай, т.к. их назначение как раз в проверке предусловий, которые никогда не должны нарушаться. |
Сообщ.
#38
,
|
|
|
Цитата Qraizer @ Как этот механизм будет использован программистом – это его личное дело. По ряду причин считается, что исключения должны использоваться в исключительных случаях. Золотые слова Есть возможность использования, есть ограничения - остальное дело фантазии. "Считается" - не в счет, это демагогия. Есть здравый смысл. Пример синтаксиса: функция() { } функция() { } функция() { } Здравый смысл подсказывает, что оформление первых двух функций удобно, третьей - если она на залезает за границы экрана. Иначе неудобно. Так и с исключениями - их можно везде использовать, где можно. Главное, чтобы логика не ломала моск. Обработка "обрабатываемых" ситуаций - тут ни разу не противоречит здравому смыслу. Следовательно придавать смысл "исключительным" ситуациям значения "фатально-непоправимых" - есть субъективное аффторство субъективного аффтора. Имхо. |
Сообщ.
#39
,
|
|
|
Конечно. Но есть нюанс.
К примеру субъективное мнение автора сказало ему, что использовать исключения для управления потоком исполнения вполне себе удобно и нормально. Т.е. он решил построить свой код на архитектуре, шитой процитированной выше третьей причиной. Получается, что субъективное мнение автора убедило его, что нелокальные переходы – это нормально и удобно. Пусть теперь сей автор подумает и заценит, что скажут о его коде другие, если б он писал его в стиле С, т.е. на <setjmp.h>. Как бы "ненуачё, мне нужны нелокальные переходы" разбивается об холивар о goto. |
Сообщ.
#40
,
|
|
|
Цитата Qraizer @ Более того, обычно не то что "негарантированно отказоустойчиво", а как правило даже "гарантированно отказосоздающе". Иногда даже в рамках чистого C-кода. Использование нелокальных переходов в стиле C вне исключительно C-кода запрещено в связи с их негарантирующей отказоустойчивостью. |
Сообщ.
#41
,
|
|
|
Цитата Qraizer @ Получается, что субъективное мнение автора убедило его, что нелокальные переходы – это нормально и удобно. Если это не ломает читабельный стиль и одновременно не приносит излишних расходов по производительности, объему кода - я ничего предосудительного не вижу. Тем более, если мы говорим о структурной обработке исключения, то сам термин "структурная" говорит о том, что пишем нормально, а не левой ногой. |
Сообщ.
#42
,
|
|
|
Нет, мы говорим о C++EH.
P.S. Оффтоп. Кстати, кто тебе сказал, что "структурная", которая SEH, имеет какое-то отношение к структурному программированию? Это всего лишь означает, что структурно оформляются охраняемые блоки и блоки обработки. Однако переходы по этим блокам – это не просто какие-то там goto, которые прыгают строго по статичным меткам. Это вычислимые goto, которые прыгают невесть куда, это только в run-time будет известно. |
Сообщ.
#43
,
|
|
|
Ну это понятно, там, на сколько я понимаю, еще и раскрутка стека. Ну так - это не единственный сюрприз Цэ++. Возьми те же неявные конструкторы. Мало-ли как "оно, то или другое" там внутри работает - главное как мы видим и правильно ли оформляем.
И второй момент, раз нам дана возможность наследоваться от классов исключений - значит это возможность, и ею законно можно пользоваться. |
Сообщ.
#44
,
|
|
|
Цитата Qraizer @ Убирание ассертов из релиза не является неотъемлемым их свойством. Если ассерты дают существенный минус к производительности у тебя всегда есть выбор пожертвовать ассертами ради производительности. Я вовсе не утверждаю, что ассерты необходимо обязательно удалять из релиза.В том-то и прикол, что опасаться нужно всегда. Откуда уверенность, что под-assert()-ные проверки больше не потребуются никогда в жизни на протяжении жизненного цикла? Цитата Qraizer @ Я вот не пойму зачем сравнивать исключения/setjmp с ассертами? Ассерты - это завершение программы в случае обнаруженного UB, в тоже время как исключения/setjmp - вполне себе определенное поведение. Допустим произошло нарушение некоторого контракта по неведомым причинам. Объект стал невалидным и дальнейшее выполнение программы (в том числе и раскрутка стека, вызов деструкторов и т.п.) превращается в сплошное UB. Накой тут исключение/setjmp? Единственный верный путь в данном случае - диагностическое сообщение и аварийное завершение программы.assert() с его abort()-ом был более-менее приемлем для C, но там и <setjmp.h> вполне себе в теме. Исключения в C++ были введены с той же целью, что и <csetjmp>, однако они в отличие от нелокальных прыжков совместимы с локальными объектами в общем и RAII в частности. Если abort() хоть как-то обоснован в C, там нет объектов, то в C++ его ниша исчезающе мала, если не вообще нулевая. Цитата Qraizer @ Можно подумать что вот это твое личное спорное мнение - не лирика. Назначение исключений - предоставление возможности выполнить нелокальный переход??? Нет, я конечно не спорю, что исключение можно с некоторой натяжкой назвать нелокальным переходом, но это ни разу не его (исключения) назначение. Назначение исключений - обеспечивание удобной обработки не просто исключительных, а ожидаемо исключительных событий.Это лирика. Главное назначение исключений в предоставлении способа осуществления нелокальных переходов, безопасного к инвариантам. Как этот механизм будет использован программистом – это его личное дело. Цитата Qraizer @ Подчеркнутое спорно. При желании любая функция может вернуть признак ошибки, возвращая кортеж из результата и флага ошибки. Вроде в Rust именно такой подход. Тут скорее дело не в возможности/невозможности вернуть код ошибки, чистой воды религиозные запреты. Правда возврат ссылок на не существующие объекы действительно проблема, но при желании таки можно создать ссылку на null. Невозможность функции/методу исполнить свой контракт при невозможности вернуть признак ошибки. Примером может служить функция, возвращающая ссылку на объект в случае невозможности создать таковую, т.к. ссылок на NULL не существует. Цитата Qraizer @ Да, но повторяю, assert- это не нелокальный переход. Ассерт не просто не гарантирует отказоустойчивость, а напротив гарантирует отказ. При крайней необходимости осуществить нелокальный переход в стиле <csetjmp>. Использование нелокальных переходов в стиле C вне исключительно C-кода запрещено в связи с их негарантирующей отказоустойчивостью. |
Сообщ.
#45
,
|
|
|
applegame, я был бы не против assert()ов, если, во-первых, использовать их наоборот – для выявления мест возникновения багов вместо контроля их отсутствия; во-вторых, вместо abort() они бы плюхали мне отладчик на монитор. Однако первое оказывается ненужным после выявления места бага, второе невозможно по определению assert()-а в Стандарте. Так что фтопку.
Цитата applegame @ Я и не сравниваю. Я утверждаю, что assert() бесполезен, у него тупо нет вменяемой ниши. Предположим, да, произошло нарушение инварианта. И что? Это проблема конкретного экземпляра конкретного класса. Если это единственный класс на всю программу, а ещё лучше единственный экземпляр этого класса, то соглашусь. Да, конкретно вот это – ниша assert()-а. В любом же другом случае, объясни, плз, чем провинились другие классы и экземпляры? Тут тоже можно найти нишу, в особых классах с высочайшим уровнем ответственности и влиянием на всё операционное окружение, только она исчезающе мала.Я вот не пойму зачем сравнивать исключения/setjmp с ассертами? Ассерты - это завершение программы в случае обнаруженного UB, в тоже время как исключения/setjmp - вполне себе определенное поведение. Допустим произошло нарушение некоторого контракта по неведомым причинам. Объект стал невалидным и дальнейшее выполнение программы (в том числе и раскрутка стека, вызов деструкторов и т.п.) превращается в сплошное UB. Накой тут исключение/setjmp? Единственный верный путь в данном случае - диагностическое сообщение и аварийное завершение программы. А проблема конкретного экземпляра конкретного класса решается куда изящнее ...исключением, которое нигде не перехватывается. Поставил обработчик неперехваченных, получил в нём это особое исключение, вытащил оттуда нужную инфу, молотком привёл экземпляр во вменяемое состояние, заменил на нормальное исключение, бросил, размотал стек и вышел. Цитата applegame @ Назначение исключений – заменить <csetjmp>, а уже назначение последнего – нелокальные переходы. Вывод ИМХО очевидный. Можно использовать средства не по их назначению, ничего плохого в этом нет. Кроме как если такое использование неоправданно.Назначение исключений - предоставление возможности выполнить нелокальный переход??? Нет, я конечно не спорю, что исключение можно с некоторой натяжкой назвать нелокальным переходом, но это ни разу не его (исключения) назначение. Назначение исключений - обеспечивание удобной обработки не просто исключительных, а ожидаемо исключительных событий. Цитата applegame @ Да. Но в большинстве случаев это неудобно и ненадёжно. Заметь, то цитата из стандарта кодирования, поэтому надёжный код – это основная мотивация его пунктов. С моей точки зрения в критически важных для надёжности случаях нельзя оставлять человеку возможность ошибиться и забыть проверить состояние ошибки. Исключение проигнорить не получится, а если такое и произойдёт... то это не ассерт, в конце концов. Подчеркнутое спорно. При желании любая функция может вернуть признак ошибки, возвращая кортеж из результата и флага ошибки. |
Сообщ.
#46
,
|
|
|
Цитата Qraizer @ Им просто не повезло: класс с которым они должны взаимодействовать стал невалидным. В любом же другом случае, объясни, плз, чем провинились другие классы и экземпляры? Цитата Qraizer @ Начиная с "молотком привел экземпляр..." пожалуйста поподробнее. Что ты имеешь в виду? А проблема конкретного экземпляра конкретного класса решается куда изящнее ...исключением, которое нигде не перехватывается. Поставил обработчик неперехваченных, получил в нём это особое исключение, вытащил оттуда нужную инфу, молотком привёл экземпляр во вменяемое состояние, заменил на нормальное исключение, бросил, размотал стек и вышел. |
Сообщ.
#47
,
|
|
|
Сделал его инвариантным, чтобы мог нормально деструкнуться.
Добавлено Например, тупо выставить поле m_size в 0 у контейнера. |
Сообщ.
#48
,
|
|
|
Цитата Qraizer @ А проблема конкретного экземпляра конкретного класса решается куда изящнее ...исключением, которое нигде не перехватывается. Поставил обработчик неперехваченных, получил в нём это особое исключение, вытащил оттуда нужную инфу, молотком привёл экземпляр во вменяемое состояние, заменил на нормальное исключение, бросил, размотал стек и вышел. По-моему и у нас с тобой случился разговор из разряда: - трава же зеленого цвета?! - нет, пол-восьмого! Процитированное тобой именно я и утверждал выше. Ловим возможные исключения. Если удается привести процесс выполнения в нужное состояние - приводим в обработчиках исключений. Если не получается -> вывод причины + отмена операции (или вовсе полное завершение программы). А ты мне про какие-то длинные прыжки рассказываешь Ну не вписывается все это в структурное программирование, но удобно и понятно. "Неструктурным черным ящичкам" - жить! |
Сообщ.
#49
,
|
|
|
Цитата Qraizer @ Весьма плохо себе это представляю. Допустим из-за переполнения буфера в сторонней библиотеке, указатель на некий объект стал указывать неизвестно куда. Каким интересно молотком его выравнивать? Сделал его инвариантным, чтобы мог нормально деструкнуться. |
Сообщ.
#50
,
|
|
|
Цитата applegame @ Допустим из-за переполнения буфера в сторонней библиотеке, указатель на некий объект стал указывать неизвестно куда. Каким интересно молотком его выравнивать? Лично я бы в таком случае реализовал выход из программы по assert'у. Чужие либы с багами - это мина на неизвлечении. |
Сообщ.
#51
,
|
|
|
Впрочем во многом Qraizer прав. В общем случае ассерты вполне себе годная штука, но реализация их в C++ все же корявая. Я так подумал, на самом деле ассерты в виде полноценных исключений, мне нравятся больше (в D именно такие). Просто нужно нарисовать грамотную иерархию исключений. Например создать некий assert_error, который унаследовать от std::logic_error и в большинстве случаев, вместо ассертов, спокойно кидаться им. Иногда ассерты ловить полезно, у меня есть моменты в проекте (на D), где нарушение инварианта - вполне себе обрабатываемое событие: просто убивается файбер/сопрограмма вместе с UB, которое создалось из-за нарушения контрактов. Само приложение продолжает работать. А возникшее UB обнаружитвается в логах и впоследствии лечится.
|
Сообщ.
#52
,
|
|
|
Просто assert'ы были сделаны не для C++. И планировалось пользоваться ими только для целей нарушения условий, в основном во время отладки. Поэтому при объявлении NDEBUG ассерты превращаются в простые нолики. Поэтому и работают не так, как следовало бы, чтобы они нормально вписывались в C++.
Для C++ действительно лучше иметь отдельную от C реализацию такой проверки. |
Сообщ.
#53
,
|
|
|
Цитата JoeUser @ Правильно. Холивар о goto можно закрывать."Неструктурным черным ящичкам" - жить! amk, тут дело даже не в языке, по-моему. Просто с тех бородатых времён, когда C только появился, сами технологии проектирования ПО изменились. Сейчас даже в C просто прибивать процесс assert()-ом не всегда удачная идея при нынешнем положении дел в индустрии. Добавлено Цитата applegame @ Та хоть new char. Не всё ли равно? Лишь бы delete в деструкторе ублажить. Допустим из-за переполнения буфера в сторонней библиотеке, указатель на некий объект стал указывать неизвестно куда. Каким интересно молотком его выравнивать? Добавлено P.S. Ты, видимо, не знаком с принципами проектирования критически надёжного кода. Ну, это моя вина, я только с таким последние 10 лет только и связан по роду деятельности, поэтому как-то уже не приемлю других критериев просто по привычке. Один из основополагающих факторов – отказ работоспособности одной подсистемы не должен приводить к отказам в других. Так что проблемы конкретного объекта должны оставаться его личными проблемами. |
Сообщ.
#54
,
|
|
|
Цитата Qraizer @ Не то чтобы совсем не знаком. Но опыта маловато. Фактически только последний проект стараюсь писать с подобным подходом. Так как терять реальные деньги из-за несмертельных ассертов не хочется. P.S. Ты, видимо, не знаком с принципами проектирования критически надёжного кода. Ну, это моя вина, я только с таким последние 10 лет только и связан по роду деятельности, поэтому как-то уже не приемлю других критериев просто по привычке. Один из основополагающих факторов – отказ работоспособности одной подсистемы не должен приводить к отказам в других. Так что проблемы конкретного объекта должны оставаться его личными проблемами. |
Сообщ.
#55
,
|
|
|
Стоп, а вы про классические assert'ы говорите, которые из #include <assert.h>? Эти вообще нигде и никак не надо использовать. Вместо них нужны свои макросы, которые и дамп для отладчика сделают, и все логи корректно закроют, и всякую другую полезную информацию сохранят (посмертный скриншот например и значения ключевых данных).
|
Сообщ.
#56
,
|
|
|
Цитата Pacific @ Эти вообще нигде и никак не надо использовать. Прям вот так вот категорично? А если мне не нужны скриншоты, если логирование не имеет своей собственной буферизации(т.е. достаточно того, что файлы будут закрыты при смерти процесса), если для отладки мне вполне достаточно корки, которую сделал этот самый assert? |
Сообщ.
#57
,
|
|
|
Цитата Pacific @ А также посмертный список паролей, адресной книги и прочей неконфиденциальной информации. посмертный скриншот например |
Сообщ.
#58
,
|
|
|
Цитата D_KEY @ Прям вот так вот категорично? А если мне не нужны скриншоты, если логирование не имеет своей собственной буферизации(т.е. достаточно того, что файлы будут закрыты при смерти процесса), если для отладки мне вполне достаточно корки, которую сделал этот самый assert? А вызов abort откладывает корку? Давно я это говно не вызывал... В любом случае, отладчики с этим говном дружат плохо, что выявляется при попытке воспроизвести баг. Сишные ассерты должны умереть. |
Сообщ.
#59
,
|
|
|
applegame
Я про внутренние билды для тестеров говорю. |
Сообщ.
#60
,
|
|
|
Цитата MyNameIsIgor @ Сишные ассерты должны умереть. Кому должны? Умирает то, что не используют. Они итак еле живы, но иногда их используют, а значит и умирать они не должны. |
Сообщ.
#61
,
|
|
|
Цитата D_KEY @ Кому должны? Мне. Цитата D_KEY @ Они итак еле живы, но иногда их используют, а значит и умирать они не должны. Должны. Всем лучше послушать Qraizer'а и вставить исключения. |
Сообщ.
#62
,
|
|
|
Цитата applegame @ А также посмертный список паролей, адресной книги и прочей неконфиденциальной информации. Кстати, в обычном дампе все это тоже вполне может оказаться... |
Сообщ.
#63
,
|
|
|
Цитата MyNameIsIgor @ В любом случае, отладчики с этим говном дружат плохо Зря ты так. Дамп хорошо показывает стек вызовов. А это верное направление что и где проанализировать, где ассертов наставить. Цитата MyNameIsIgor @ А вызов abort откладывает корку? Если это разрешено настройками системы. |
Сообщ.
#64
,
|
|
|
Цитата JoeUser @ Зря ты так Я про abort |
Сообщ.
#65
,
|
|
|
Цитата MyNameIsIgor @ Всем лучше послушать Qraizer'а и вставить исключения. А в обработчике исключения вызвать abort() Добавлено Цитата MyNameIsIgor @ Я про abort Ну так я и говорю, не вызовешь abort() или что недежнее kill(getpid(), SIGABRT), не получишь дамп. Не получишь дамп - не видать тебе стека вызовов малой кровью. |
Сообщ.
#66
,
|
|
|
Цитата JoeUser @ Ну так я и говорю, не вызовешь abort() или что недежнее kill(getpid(), SIGABRT), не получишь дамп. Не получишь дамп - не видать тебе стека вызовов малой кровью. Но с исключениями отладчики дружат и умею останавливаться по факту их выброса. |
Сообщ.
#67
,
|
|
|
Цитата MyNameIsIgor @ Цитата JoeUser @ Ну так я и говорю, не вызовешь abort() или что недежнее kill(getpid(), SIGABRT), не получишь дамп. Не получишь дамп - не видать тебе стека вызовов малой кровью. Но с исключениями отладчики дружат и умею останавливаться по факту их выброса. Ну мы уже спорили выше, где ниша исключений, где ассертов. Если исключениями обрабатывать предполагаемые "коллизии", их можно обработать явно и корректно восстановить работу, ну или корректно заваершить с логом. А вот ассерты ставить там, где ошибка маловероятна, но может быть, и главное по каким хз причинам. Можно на период ввода в эксплуатацию отдать Заказчику дебаг-версию и ждать время "ч". Если таки случится ахтунг - можно получить заветный баг-репорт по почте, включая и дамп, и без участия Юзера. Но заставить юзера поработать под отладчиком ... слабо представляемо. |
Сообщ.
#68
,
|
|
|
Цитата MyNameIsIgor @ Цитата JoeUser @ Ну так я и говорю, не вызовешь abort() или что недежнее kill(getpid(), SIGABRT), не получишь дамп. Не получишь дамп - не видать тебе стека вызовов малой кровью. Но с исключениями отладчики дружат и умею останавливаться по факту их выброса. Но для этого тебе нужно уже запуститься под отладчиком. А это не всегда так просто. Иногда удобнее иметь корку, в которой уже найти причину сбоя. |
Сообщ.
#69
,
|
|
|
Цитата JoeUser @ А вот ассерты ставить там, где ошибка маловероятна, но может быть, и главное по каким хз причинам Офигенный подход к разработке софта Цитата JoeUser @ Но заставить юзера поработать под отладчиком Цитата D_KEY @ Но для этого тебе нужно уже запуститься под отладчиком. А это не всегда так просто. Иногда удобнее иметь корку, в которой уже найти причину сбоя. Вот интересно: в каких ещё языках корку снимают? |
Сообщ.
#70
,
|
|
|
Цитата MyNameIsIgor @ Цитата D_KEY @ Но для этого тебе нужно уже запуститься под отладчиком. А это не всегда так просто. Иногда удобнее иметь корку, в которой уже найти причину сбоя. Вот интересно: в каких ещё языках корку снимают? Мне кажется, что во всех компилируемых и нативных. Из тех, что используют |
Сообщ.
#71
,
|
|
|
Цитата D_KEY @ Мне кажется, что во всех компилируемых и нативных А мне кажется, что нигде больше такой фигнёй не страдают. Почему, кстати, компилируемые выделил? У остальных не может быть ситуации, когда корка удобнее? Добавлено Вообще, удивительно. Только плюсовиков надо убеждать использовать исключения. Не видел ещё лозунгов "Даёшь C# без исключений!" С этими аасертами та же песня - наследие древнее говна мамонта, но всё равно: в любой непонятной ситуации закхреначь программу ассертом! |
Сообщ.
#72
,
|
|
|
Цитата MyNameIsIgor @ Цитата D_KEY @ Мне кажется, что во всех компилируемых и нативных А мне кажется, что нигде больше такой фигнёй не страдают. Почему, кстати, компилируемые выделил? У остальных не может быть ситуации, когда корка удобнее? Ну я плохо себе представляю, что за корка будет в этом случае. Бегать по коду интерпретатора мне как-то не кажется удобным. |
Сообщ.
#73
,
|
|
|
Цитата D_KEY @ Ну я плохо себе представляю, что за корка будет в этом случае. Бегать по коду интерпретатора мне как-то не кажется удобным. Будет не корка интерпретатора, а корка для интерпретатора. |
Сообщ.
#74
,
|
|
|
Цитата MyNameIsIgor @ Цитата D_KEY @ Ну я плохо себе представляю, что за корка будет в этом случае. Бегать по коду интерпретатора мне как-то не кажется удобным. Будет не корка интерпретатора, а корка для интерпретатора. Ну тогда еще можно, да. Но это нужно отдельно реализовывать. |
Сообщ.
#75
,
|
|
|
Цитата MyNameIsIgor @ Офигенный подход к разработке софта Нормальный подход - а как ты думаешь Майкрософт свои денежки подзаработала? На хваленой XP одних сервиспаков аж три, и четвертый неофициальный. Такшта не надо песен, что ты пишешь кристально чистый код. У всех сроки и объемы. Добавлено Цитата MyNameIsIgor @ наследие древнее говна мамонта Ух ты ... какой убедительный аргумент! Надо себе записать на память |
Сообщ.
#76
,
|
|
|
Ненормальный. Защищаться от бяк чужого кода надо всегда, и ассерты тут не помогут, если ты не хочешь, чтобы тебя разыскивали с цепками и битами по причине утерянной работы из-за помахавшей ручкой abort(). Наверное ты предпочтёшь, чтобы разыскивали автора чужого кода, не так ли? А защищаться от бяк своего кода гораздо удобнее в чётко тебе известных точках, проверяя чётко тебе известные инварианты.
Добавлено Цитата JoeUser @ А ты поинтересуйся, сколько там исправлений ошибок Майкрософта, сколько расширений функционала, отсутствовавшего в 2001-ом, и сколько патчей совместимости с говноизделиями Компаний с Большим Именем, которые понапхали в свои говнопродукты килотонны юзов недокументированностей и, в частности ассертами, решили их контролировать. Для примера: поддержка PCIE появилась в SP2, а до этого XP содержала кернельный баг: не поддерживала ещё не существующее железо. На хваленой XP одних сервиспаков аж три... |
Сообщ.
#77
,
|
|
|
Qraizer, таки, десктопные оси - это вам не прошивки для спутников писать Можно слегка схалтурить ради прибыли.
|
Сообщ.
#78
,
|
|
|
Цитата Qraizer @ Ненормальный. Защищаться от бяк чужого кода надо всегда, и ассерты тут не помогут, если ты не хочешь, чтобы тебя разыскивали с цепками и битами по причине утерянной работы из-за помахавшей ручкой abort(). Аргумент мимо. Для того, чтобы не потерять утерянную работу, нужно бэкапиться по приемлимому по времени или действиям регламенту. Пример M$ Word. Сколько я его полетов наблюдал ... но ... фсегда есть скрытый файлик типа "~твой досумент.doc", в котором есть все действия, кроме последней нажатой точки, где и был сбой. Цитата Qraizer @ А защищаться от бяк своего кода гораздо удобнее в чётко тебе известных точках, проверяя чётко тебе известные инварианты. Инвариантов НЕ-БЫ-ВА-ЕТ. Тому подтверждение - утилиты memtest, victoria Цитата Qraizer @ Если ты не хочешь, чтобы тебя разыскивали с цепками и битами по причине утерянной работы из-за помахавшей ручкой abort() ... Наверное ты предпочтёшь, чтобы разыскивали автора чужого кода, не так ли? Щя лирики налью, мама-не-горюй! Ну, давай про TCP/IP ... Исправимая ситуация Ты решил сохранить файл по HTTPS. Но прилетел злой дятел и раздолбал маршрутизатор на березе. Все, DNS отвалился, а вторичный DNS еще неотрезольвил IP твоего HTTP-сервера по URI. Ситуация в принципе не из ряда вон. Обрабатывая исключение записи, программа может уведомить после n-попыток о сбое, предложить сохранить файл локально. Все ровно и никто ни за кем не бегает, и тут не место ассерту, и дятел почти неуиновен. Неисправимая ситуация Ты внедрил ноу-хау - систему управления гильотиной на базе Raspberry PI. Регламент простой, после почтения обвинения присяжные на своих АйПадах жмут кнопку "Косяк обвинения", если нажали 51% из числа присяжных - обвиняемый оправдан. Иначе через 37 сек - работает гильотина. И тут ... прилетел дятел! Раздолбал ви-фи роутер и улетел. Время идет, соединения нет. Как обработать исключительную ситуацию??? Обработать эксепшен в стиле "Сохранить решение для следующего обвиняемого???" Разницы нет - ассерт - эксепшен !!! В результате обвиняемому отрубили дреды за антиобщественное поведение (они оказались вымытыми и ухоженными). Но это не тот чел, который будет гоняться, такие обычно стремные. Представь если кому нить что нить отрубят по ошибке за попытку изнасилования! А вот исследование корки даст профит - стек вызовов... А пинговал ли ты, мил человек, Raspberry PI загодя??? Скрытый текст Хотя ... может и тут дятел неуиновен Raspberry PI то работает под операционной системой "Pidora". Короче, как назовешь яхту ... будет она ходить по морю или плавать ... Как-то так |
Сообщ.
#79
,
|
|
|
JoeUser, давай ты просто не будешь пробовать аргументировать свои выводы фактами из областей, о которых ничего не знаешь?
Цитата JoeUser @ Дальше можно было бы не читать. Но я прочёл. Да, можно было бы. Инвариантов НЕ-БЫ-ВА-ЕТ. |
Сообщ.
#80
,
|
|
|
Цитата Qraizer @ Дальше можно было бы не читать. Но я прочёл. Да, можно было бы. |
Сообщ.
#81
,
|
|
|
Цитата Qraizer @ JoeUser, давай ты просто не будешь пробовать аргументировать свои выводы фактами из областей, о которых ничего не знаешь? Ну тут недосказанность. Если это просьба рядового участника форума - я пожалуй воздержусь от этого "вопроса-совета" и посопротивляюсь. Если это телега модератора о нарушении - хотелось бы подробностей "где и в чем". Ну и собственно больше бы инфы о тех "неведомых мне областях" ... давай на примерах посмотрим. Тока просьба аппелировать к статистике а не к наличию. Добавлено Цитата Qraizer @ Дальше можно было бы не читать. А чего читать. Есть СТАНДАРТ, помолился и норм день прошел. |
Сообщ.
#82
,
|
|
|
JoeUser, что тут апеллировать. Просто всё писанное мимо.
|
Сообщ.
#83
,
|
|
|
Цитата Qraizer @ JoeUser, что тут апеллировать. Просто всё писанное мимо. Ну не знаю как тебе там твое видно. Мне лично так: "я знаю секрет, но не скажу. несогласные - дураки". Ну не хочешь предметно говорить, твое право, как и мое - не верить "мамой клянус, прямоугольник - прямоугольный" Добавлено Цитата MyNameIsIgor @ Подхалим |
Сообщ.
#84
,
|
|
|
Цитата MyNameIsIgor @ Вообще, удивительно. Только плюсовиков надо убеждать использовать исключения. Не видел ещё лозунгов "Даёшь C# без исключений!" Потому, что от стандартных исключений в C++ мало толку. В отличие от. Потому, что исключения таки могут замедлить код в C++. Потому, что в C# нельзя сделать корку и сравнивать им не с чем. И да, конкретно меня убеждать не надо, я использую исключения. Но я не понимаю, почему их должны использовать все и всегда. Пусть люди сами для своих проектов выбирают то, что им подходит(как они думают), они же и будут потом с этим жить. Цитата С этими аасертами та же песня - наследие древнее говна мамонта, но всё равно: в любой непонятной ситуации закхреначь программу ассертом! Ну... А почему нет? Кстати, примеров с assert'ом много в литературе. Даже у Страуструпа с Саттером. Не нравится - не используй. Я вот сейчас не использую. Добавлено Цитата Qraizer @ Ненормальный. Защищаться от бяк чужого кода надо всегда, и ассерты тут не помогут, если ты не хочешь, чтобы тебя разыскивали с цепками и битами по причине утерянной работы из-за помахавшей ручкой abort(). Наверное ты предпочтёшь, чтобы разыскивали автора чужого кода, не так ли? А защищаться от бяк своего кода гораздо удобнее в чётко тебе известных точках, проверяя чётко тебе известные инварианты. Зачем вы пытаетесь найти какие-то общие рецепты? Бывают случаи, когда даже память динамическую в программе бессмысленно освобождать(т.к. единственный эффект от такого "корректного" освобождения заключается в том, что процесс будет дольше завершать свою работу). Задачи бывают разные и рецепты, соответственно, тоже. Добавлено Цитата JoeUser @ Цитата Qraizer @ А защищаться от бяк своего кода гораздо удобнее в чётко тебе известных точках, проверяя чётко тебе известные инварианты. Инвариантов НЕ-БЫ-ВА-ЕТ. Ну это совсем уже... Хотя, как показывает практика собеседований, понятие инвариантов знакомо немногим |
Сообщ.
#85
,
|
|
|
Цитата D_KEY @ Хотя, как показывает практика собеседований, понятие инвариантов знакомо немногим Давай только не будем о сферических конях в вакууме Можно напридумывать тучу синтетических условий, систем отсчета, шкальных оценок - это все модели, МОДЕЛИ!!!! которые приближенно отражают реальную картину мира. Мир - иррационален! Двоичная система аппаратной реализации инвариантна? До поры до времени ... до первых сбоев. Дальше - только в расчет берутся плотности вероятностей. Инварианты - это математические фикции, дабы подшлифовать ваши модели, не более. Добавлено Ну и вдогоночку ... о ней самой ... Цитата Переход от обсуждения предмета спора к обсуждению личности (аргумент к личности) Вместо того, чтобы доказывать истинность своих положений и опровергать аргументацию оппонента, демагог может обращаться к приёму ad hominem — критиковать не аргументы, а личность оппонента, пытаясь убедить зрителей, что оппонент — плохой, недостойный, не разбирающийся в вопросе, пристрастный или лицемерный человек. Что может сказать об архитектуре мужчина без прописки? (М. Жванецкий) |
Сообщ.
#86
,
|
|
|
Цитата JoeUser @ Нет, это всего лишь означает предложение ознакомиться с предметной областью перед продолжением обсуждения инвариантов, высококритичного кода и гарантий отказоустойчивости. Мне лично так: "я знаю секрет, но не скажу. несогласные - дураки". |
Сообщ.
#87
,
|
|
|
Ну если только чел выше уберет свои "справедливейшие замечания", а по факту съезд на личности. А так ... не уберу, ты модер - тебе и рулить, делай как поступаешь правильным. |
Сообщ.
#88
,
|
|
|
Цитата D_KEY @ Мне <stdexcept> хватает, но я и не пишу сейчас что-либо сложнее внутриконторных утилит для внутреннего использования. Хотя "компилятор" не скажу, что простая утилита. Основное назначение <exception> в предоставлении базы, а дальше расширяйте, как удобно.Потому, что от стандартных исключений в C++ мало толку. Цитата D_KEY @ Могут, когда они происходят. longjmp() будет быстрее? Безусловно. Однако как часто ты его встречаешь в программах на C? Так что, ситуации назвали исключительными просто так?Потому, что исключения таки могут замедлить код в C++. Если попробовать заимплементить функционал C++EH самостоятельно, то либо получится то же самое, либо это будет частное решение под конкретную ситуацию. К тому же изобилующее местами, куда влёгкую дотянется человеческий фактор. Цитата D_KEY @ Потому, что это примеры. Так короче и понятнее, чем словами в комментариях. Кстати, примеров с assert'ом много в литературе. Даже у Страуструпа с Саттером. |
Сообщ.
#89
,
|
|
|
У меня завтра уже сегодня. Рули как знаешь. Я не флюгер. Ну а пока не словил банку, отвечу по существу. По поводу "отказоустойчивости". Да, ты прав, этот вопрос я не изучал досконально (хотя вопрос поднят и я его изучу). Краем уха слышал о 12-ти кратности в космонавтике. Простыми словами "12-и кратная, независимая, страховка сводит к обозримому нулю потери". Правда это или треп, сейчас сказать не могу. За что купил - за то продаю. Только к чему это все??? Если дашь линки на "полезное" и "эффективное" применение страховки в программировании - буду благодарен. А пока вижу только мистику и браваду. Напомню, немножко и очень скромно, я никому не верю, вне зависимости лаборант он на кафедре или профессор (пока сам не разберусь). Как говорят киргизы, се ля ви. |
Сообщ.
#90
,
|
|
|
Цитата JoeUser @ Больше похоже на трёп. Подобное резервирование производится только для систем, от которых зависит выживание экипажа. Часто резервирование заменяется на дублирование. То есть функции отказавшей системы берёт на себя другая, для которой функция первой м.б. не входит в число основных.Правда это или треп, сейчас сказать не могу. Ты ведь никогда не слышал, чтобы на каждого космонавта в космос брали по 12 скафандров? |
Сообщ.
#91
,
|
|
|
Цитата amk @ Ты ведь никогда не слышал, чтобы на каждого космонавта в космос брали по 12 скафандров? Абсолютно не в курсе по сколько там берут Добавлено Хотя интересно Эта инфа о 12-кратной страховке запомнилась уже и не знаю когда. Щя задался вопросом, откуда эти ноги растут Добавлено Погуглил, пока нашел в различных местах инфу о требовании 12-кратного запаса по прочности (истребители, канаты, альпинистское снаряжение ...), по току (регуляторы мощности) Про дублирование функций управляющих систем не нашел. Мистика. |
Сообщ.
#92
,
|
|
|
Я вот задаюсь вопросом, почему некоторые так не любят исключения. Вообще не любят. Например, их выбросили из Rust и Go. Аргументация разработчиков Go какая-то никудышная:
Цитата https://golang.org/doc/faq#exceptions We believe that coupling exceptions to a control structure, as in the try-catch-finally idiom, results in convoluted code. It also tends to encourage programmers to label too many ordinary errors, such as failing to open a file, as exceptional. Go takes a different approach. For plain error handling, Go's multi-value returns make it easy to report an error without overloading the return value. A canonical error type, coupled with Go's other features, makes error handling pleasant but quite different from that in other languages. Go also has a couple of built-in functions to signal and recover from truly exceptional conditions. The recovery mechanism is executed only as part of a function's state being torn down after an error, which is sufficient to handle catastrophe but requires no extra control structures and, when used well, can result in clean error-handling code. "Поощряет программистов считать многие обычные ошибки, таких как ошибка открытия файла, исключительными.". Такое впечатление, что в Google ошибки открытия файла - это штатная ситуация. |
Сообщ.
#93
,
|
|
|
Цитата JoeUser @ Время идет, соединения нет. Как обработать исключительную ситуацию??? Обработать эксепшен в стиле "Сохранить решение для следующего обвиняемого???" Разницы нет - ассерт - эксепшен !!! Отловили ексепшн — нормально (при)остановили гильотину. Выбросился ассерт — ПО потеряло контроль над железом, гильотина пустилась в свободное плавание, КРОВЬ-КИШКИ-РАСПberry Pi. Добавлено Цитата applegame @ "Поощряет программистов считать многие обычные ошибки, таких как ошибка открытия файла, исключительными.". Такое впечатление, что в Google ошибки открытия файла - это штатная ситуация. Ошибка открытия файла — вполне себе обыденная ситуация. Не помню где, читал так же мнение, что с исключениями как-то не всё однозначно в конкуррентном коде. |
Сообщ.
#94
,
|
|
|
Цитата korvin @ Такая вот прямо обыденная, что даже исключения недостойна? Если там какой-то ну совсем уж необязательный файл, то что мешает перед открытием сначала проверить его наличие?Ошибка открытия файла — вполне себе обыденная ситуация. Цитата korvin @ Интересно, что именно с ними не так однознчно? У них вроде только один недостаток - некоторый оверхед, который в некоторых случаях может быть нежелателен. Не помню где, читал так же мнение, что с исключениями как-то не всё однозначно в конкуррентном коде. |
Сообщ.
#95
,
|
|
|
Цитата korvin @ ПО потеряло контроль над железом, гильотина пустилась в свободное плавание, Там ващета говорилось о программах на планшетах |
Сообщ.
#96
,
|
|
|
M Итак, тематического разговора не получилось. Причём, стараниями самого ТС. Передо мной выбор: банка за флуд и неподчинение модератору или снос темы во флейм. Вы знаете моё отношение к банкам, так что не удивлю, если скажу, что сам я склоняюсь ко второму варианту. Но там тема зарастёт флудом куда сильнее. Итак, каков ваш выбор? Жду до вечера. Добавлено Цитата JoeUser @ Ну вот, опять. Я ж говорю, не в теме. Надёжность железа тут ни причём, речь идёт исключительно о гарантиях отказоустойчивости софта. По поводу "отказоустойчивости". Добавлено Цитата applegame @ Никудышняя. Забей, стопудоф они просто не осилили, и сделали хорошую мину.Аргументация разработчиков Go какая-то никудышная: Что считать исключительной ситуацией, а что нет – это сугубо личное дело архитектора системы. По определению ситуация исключительна, если не позволяет далее исполнять контракт. Деление на нуль. Возврат ссылки в никуда. Не предусмотренная архитектурой ПО ситуация (привет ассертам). Вот тупо невозможно и всё тут, следующая инструкция не может быть исполнена процессором, так что единственный выход – передача управления куда-то назад, где работать ещё было можно. Если ситуация предусмотрена архитектурой, она априори не исключительна, а предусмотрена бизнес-логикой. |
Сообщ.
#97
,
|
|
|
Цитата applegame @ Я вот задаюсь вопросом, почему некоторые так не любят исключения. Вообще не любят. Например, их выбросили из Rust и Go. Аргументация разработчиков Go какая-то никудышная: Самое забавное, что в Go вполне можно использовать их "панику" как исключения: func trowException() { fmt.Println("Throwing 'exception'") panic("'exception'") } func main() { defer func() { if r := recover(); r != nil { fmt.Println("Catching ", r) } }() trowException() } Так что "отказ", по моему, выглядит просто как "мы сделаем исключения неудобными и не будем поощрять их в АПИ". Опять же, постулируется, что "традиционные исключения" неудобные и неявно нарушают поток выполнения, но по моему гошное решение ничем не лучше. А по читаемости так ещё и хуже, более очевидных, try/catch блоков. Может, конечно, я чего-то не понимаю. В расте панику, кстати, тоже можно перехватывать, но только на границе потоков. В остальном всё тоже обычно - стек разматывается, деструкторы вызываются. "Возвращать" через панику можно произвольные типы. По идее, ничего не мешает и нормальным исключениям когда-то появиться. |
Сообщ.
#98
,
|
|
|
Цитата applegame @ Такая вот прямо обыденная, что даже исключения недостойна? Если там какой-то ну совсем уж необязательный файл, то что мешает перед открытием сначала проверить его наличие? А так же режим доступа и, возможно, что-то ещё. Вот это и делается, в результате выдаётся дескриптор и значение типа error, которое в случае успешной операции является просто nil, иначе содержит информацию о причинах неудачи. Всяко лучше, чем тупой false. Добавлено Но не нужно. Точнее не рекомендуется эти паники отлавливать, т.к. они сигнализируют в первую очередь об ошибке в коде (типа отсутствия проверки индекса и как следствие выхода за пределы массива), которые нужно исправить, а не о внештатной ситуации извне. Добавлено Цитата applegame @ Интересно, что именно с ними не так однознчно? У них вроде только один недостаток - некоторый оверхед, который в некоторых случаях может быть нежелателен. Сходу найти не смог, но вот на тему: http://www.lighterra.com/papers/exceptionsharmful/ Навскидку: если корутина бросила исключение, кто и где должен его поймать? Т.е. исключение либо должно обязательно ловиться внутри корутины, либо что? |
Сообщ.
#99
,
|
|
|
Цитата korvin @ А так же режим доступа и, возможно, что-то ещё. Вот это и делается, в результате выдаётся дескриптор и значение типа error, которое в случае успешной операции является просто nil, иначе содержит информацию о причинах неудачи. Всяко лучше, чем тупой false. Вообще говоря является ли ошибка открытия файла исключительно ситуацией или нет, зависит от программы. Всё сводится к Цитата Qraizer @ По определению ситуация исключительна, если не позволяет далее исполнять контракт Если мы соблюдаем контракт без файла, то ничего исключительного нет. Потому и делать следует как-то так template<typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream & s, const MutableBufferSequence & buffers); template<typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream & s, const MutableBufferSequence & buffers, boost::system::error_code & ec); |
Сообщ.
#100
,
|
|
|
Цитата korvin @ Но не нужно. Точнее не рекомендуется эти паники отлавливать Ну дык, я об этом и написал. Но это ведь никак не тянет на "отказ от исключений" (на уровне языка). Вон в С++ в стандартной библиотеке практически нет исключений. В Qt вообще нет. Но пользоваться ими не мешают. Цитата korvin @ Т.е. исключение либо должно обязательно ловиться внутри корутины, либо что? Это и для банальных колбеков актуально. Но это просто ограничения отдельных случаев. Не понимаю зачем из-за них жертвовать удобным механизмом. |
Сообщ.
#101
,
|
|
|
Цитата MyNameIsIgor @ Вообще говоря является ли ошибка открытия файла исключительно ситуацией или нет, зависит от программы. Зависит. Но какой смысл тогда собственно в исключениях? Если мы их перехватываем, то это равнозначно проверке кода ошибки. Да, исключения позволяют избавиться от вереницы if'ов, например, но в том же Хаскелле с этим не менее успешно справляются монады. Если же мы их не перехватываем, то чем они отличаются от abort() или там System.exit(EXIT_CODE)? Добавлено Цитата DarkEld3r @ Это и для банальных колбеков актуально. Но это просто ограничения отдельных случаев. Не понимаю зачем из-за них жертвовать удобным механизмом. Отдельные случаи? Конкуррентного кода становится всё больше и больше. Не понимаю, почему бы ради такого удобного механизма не пожертвовать какими-то исключениями? =) |
Сообщ.
#102
,
|
|
|
Цитата korvin @ Если мы их перехватываем, то это равнозначно проверке кода ошибки. Перехватывать мы их можем где угодно выше по стеку. Получаем такие профиты, как 1) отсутствие необходимости руками заботливо передавать ошибку и 2) полиморфные объекты ошибок позволяют передавать различную информацию об ошибке, не изменяя API. Цитата korvin @ Да, исключения позволяют избавиться от вереницы if'ов, например, но в том же Хаскелле с этим не менее успешно справляются монады. Ну, не знаю... А если мы получаем Maybe, а отдать в функцию дальнейшей обработки нам надо какой-то конкретный тип, то как без условия? |
Сообщ.
#103
,
|
|
|
Цитата DarkEld3r @ Ну дык, я об этом и написал. Но это ведь никак не тянет на "отказ от исключений" (на уровне языка). Вон в С++ в стандартной библиотеке практически нет исключений. В Qt вообще нет. Но пользоваться ими не мешают. Почему не тянет? Исходники Go открыты, ты можешь переписать его, например, без использования GC, тянет ли это на отказ от возможности вручную управлять освобождением памяти (на уровне языка)? Тебе ж никто не мешает. |
Сообщ.
#104
,
|
|
|
Цитата korvin @ Не понимаю, почему бы ради такого удобного механизма не пожертвовать какими-то исключениями? =) Погоди. А почему ради конкурентного кода необходимо жертвовать исключениями? Из-за этого? Цитата korvin @ Навскидку: если корутина бросила исключение, кто и где должен его поймать? Т.е. исключение либо должно обязательно ловиться внутри корутины, либо что? Либо концепция future/promise. |
Сообщ.
#105
,
|
|
|
Цитата korvin @ но в том же Хаскелле с этим не менее успешно справляются монады Вроде, в хаскеле тоже можно пробрасывать ошибки через несколько уровней и ловить их потом (error/catch) без оборачивания результата промежуточных функций в монады? Цитата korvin @ не менее успешно справляются монады Ещё бы с монадами как-то справиться... Ну это можно не воспринимать всерьёз, но тем не менее, хаскель далеко не мейнстрим и осилить его явно сложнее, чем тот же Gо. Цитата korvin @ Конкуррентного кода становится всё больше и больше. Не понимаю, почему бы ради такого удобного механизма не пожертвовать какими-то исключениями? =) Во первых, ещё вопрос какого кода больше. Во вторых, исключения можно использовать изолированно получая более краткий код. В третьих, что самое смешное - ими не пожертвовали. |
Сообщ.
#106
,
|
|
|
Цитата DarkEld3r @ В Qt вообще нет. Но пользоваться ими не мешают. Они в документации пишут: Цитата Preliminary warning: Exception safety is not feature complete! Common cases should work, but classes might still leak or even crash. |
Сообщ.
#107
,
|
|
|
Цитата korvin @ Почему не тянет? Потому что если мы назовём исключения "паникой", то они от этого не пропадут. Цитата korvin @ Исходники Go открыты, ты можешь переписать его, например, без использования GC, тянет ли это на отказ от возможности вручную управлять освобождением памяти (на уровне языка)? То есть, ты не видишь разницы между использованием имеющихся в языке инструментов и правкой языка? |
Сообщ.
#108
,
|
|
|
Цитата MyNameIsIgor @ Ну, не знаю... А если мы получаем Maybe, а отдать в функцию дальнейшей обработки нам надо какой-то конкретный тип, то как без условия? В смысле? Обработкой Maybe-результата и обрывом цепочки выполнения при Nothin или распаковкой при (Just x) занимаются промежуточные функции-операторы, т.е. условно код получается такой: foo = doSomething1 <?> doSomething2 <?> doSomething3 ... <?> doSomethingN где <?> — полиморфная инфиксная функция, которая и скрывает if'ы и распаковку (Just x) если ещё и написать соответствующий инстанс тайпкласа Monad, можно использовать do-нотацию без всяких <?>: foo = do doSomething1 doSomething2 doSomething3 ... doSomethingN Добавлено Цитата DarkEld3r @ То есть, ты не видишь разницы между использованием имеющихся в языке инструментов и правкой языка? Конечно нет, |
Сообщ.
#109
,
|
|
|
Цитата OpenGL @ Они в документации пишут: Ну так там они и описывают когда можно, а когда нет. Выброс исключений в слотах ничем не отличается от исключений в колбеках, по сути. Понятное дело, что из этого ничего хорошего не выйдет. Хотя раньше (подозреваю, что и сейчас, но проверять лень) они подстилали соломку: ловили такие исключения и писали в лог о неправильном использовании. |
Сообщ.
#110
,
|
|
|
M Теперь ещё и злостный оффтоп. Вы меня убедили, не будем ждать вечера. |
Сообщ.
#111
,
|
|
|
Цитата korvin @ Конечно нет, ты бы SICP почиталкомпилятор вполне себе является инструментом языка. С таким же успехом можно и бинарники патчить. Тоже "инструмент". Причём здесь SICP не понимаю. Одно дело, если нам "из самого языка" доступно изменение поведения через макросы и т.д. И совсем другое, если мы реализуем своё собственное поведение. Если у языка, хотя бы, спека есть, то это уже другой язык будет, по сути. |
Сообщ.
#112
,
|
|
|
Цитата korvin @ В смысле? Обработкой Maybe-результата и обрывом цепочки выполнения при Nothin или распаковкой при (Just x) занимаются промежуточные функции-операторы Ну, я с трудом представляю как подобное сделать для императивщины. |
Сообщ.
#113
,
|
|
|
Цитата korvin @ Да как угодно. Можно передавать исключение наружу, как например передаются исключения из future, а можно тупо перевести корутину в terminated стейт. Как тебе удобней. Навскидку: если корутина бросила исключение, кто и где должен его поймать? Т.е. исключение либо должно обязательно ловиться внутри корутины, либо что? |
Сообщ.
#114
,
|
|
|
Цитата MyNameIsIgor @ Либо концепция future/promise. Я с ней почти не знаком, как она поможет? Чем она удобней CSP/Акторов? Если взять Erlang, там же процессы могут выполняться на разном оборудовании в сети, а если взять ещё более распределённую систему, в которой разные части работаю под разными ОС'ями, написаны на разных языках, с разным рантаймом? Добавлено Цитата MyNameIsIgor @ Ну, я с трудом представляю как подобное сделать для императивщины. Так в том коде функциональщины как таковой нету, всего лишь параметрический полиморфизм да лямбды, что есть сейчас в любом языке. Да и даже это не обязательно, можно просто синтаксис для этого сделать, try-catch же тоже синтаксическая конструкция. Я тут как-то сделал почти полную копию defer/using для CL макросом и без всякой функциональщины, например. Добавлено Цитата applegame @ Да как угодно. Можно передавать исключение наружу, как например передаются исключения из future, а можно тупо перевести корутину в terminated стейт. Как тебе удобней. Наружу чего? Все корутины равноценны, нет никакой «наружи». В main-корутину? Что она будет делать с этим исключением? Если не ошибаюсь, в Джаве есть такой антипаттерн — оборачивать код main в try-catch. |
Сообщ.
#115
,
|
|
|
Цитата korvin @ Запомнить исключение, а потом передать его наружу если надо. Я с ней почти не знаком, как она поможет? Добавлено Цитата korvin @ И что? Всегда есть некая сущность их вызывающая. В асинхронных I/O системах это может быть планировщик этих самых корутин. Наружу чего? Все корутины равноценны, нет никакой «наружи» Цитата korvin @ Почему обязательно main? Если корутина сама не обработала исключение, значит можно считать что она просто подохла. Допустим во фреймворке vibe.d в случае подобного поведения файбера если ошибка дойдет до планировщика, то он просто выведет в лог сообщение, что такая-то корутина померла с такой-то ошибкой. На более высоких уровнях можно обрабатывать эти ошибки. Допусти http-сервер в случае издыхания корутины-обработчика запроса, выдает 503 ошибку.В main-корутину? Что она будет делать с этим исключением? Если не ошибаюсь, в Джаве есть такой антипаттерн — оборачивать код main в try-catch. Я очень плотно работаю с конкурентной асинхронной системой построенной на файберах и нахожу исключения архиполезными. |
Сообщ.
#116
,
|
|
|
Цитата korvin @ Я с ней почти не знаком, как она поможет? Чем она удобней CSP/Акторов? Ну, просто возврат результата. В данном случае результатом будет исключение. Цитата korvin @ Если взять Erlang, там же процессы могут выполняться на разном оборудовании в сети, а если взять ещё более распределённую систему, в которой разные части работаю под разными ОС'ями, написаны на разных языках, с разным рантаймом? В этих случаях всё равно будет какой-то маршалинг результата/ошибок. Цитата korvin @ Так в том коде функциональщины как таковой нету, всего лишь параметрический полиморфизм да лямбды, что есть сейчас в любом языке. Ну, так почему такого не сделали в Go, а вместо этого if'ы проверки ошибок? |
Сообщ.
#117
,
|
|
|
Цитата Qraizer @ Теперь ещё и злостный оффтоп. Скрытый текст Мы уже морально были готовы к переносу Цитата DarkEld3r @ Ну так там они и описывают когда можно, а когда нет. Если сверх тех ограничений, что заложены в язык, надо дополнительно оговаривать, когда можно, а когда нельзя применять исключения в данной библиотеке, то говорить о поддержке исключений в ней, имхо, неверно. Добавлено Цитата DarkEld3r @ Хотя раньше (подозреваю, что и сейчас, но проверять лень) они подстилали соломку: ловили такие исключения и писали в лог о неправильном использовании. ЕМНИП, только в дебаге. |
Сообщ.
#118
,
|
|
|
Цитата korvin @ Наружу чего? Все корутины равноценны, нет никакой «наружи». В случае future есть тот, кто запустил сопрограмму. Тот, кого интересует результат. Это, кстати, не конкурент акторов. Это скорее ближе к принципу map and reduce. В случае акторов, то в том же Erlang есть дереве наблюдения процессов, и мы можем отлавливать ошибки других процессов. |
Сообщ.
#119
,
|
|
|
Цитата applegame @ 1) И что? Всегда есть некая сущность их вызывающая. В асинхронных I/O системах это может быть планировщик этих самых корутин. 2) Почему обязательно main? Если корутина сама не обработала исключение, значит можно считать что она просто подохла. 3) Допустим во фреймворке vibe.d в случае подобного поведения файбера если ошибка дойдет до планировщика, то он просто выведет в лог сообщение, что такая-то корутина померла с такой-то ошибкой. На более высоких уровнях можно обрабатывать эти ошибки. Допустим http-сервер в случае издыхания корутины-обработчика запроса, выдает 503 ошибку. 4) Я очень плотно работаю с конкурентной асинхронной системой построенной на файберах и нахожу исключения архиполезными. 1) В этом смысл корутин, после вызова они «открепляются» от вызвавшей/создавшей их сущности и живут сами по себе. А планировщик, например, может быть встроен в рантайм и недоступен из языка. 2) Нормальный ход. Т.е. исключение просто уйдёт в никуда? Чем это отличается от простого return? 3) «И что?» В протоколе HTTP нет исключений, только коды ошибок. Ты (ну или билиотечная функция) получаешь от HTTP-сервера код ошибки, оборачивает его в исключение, ты (уже в своём коде) его отлавливаешь и передаешь дальше по HTTP код ошибки. Создал себе трудность и героически её преодолел, молодец, чё. =) 4) Молодец какой, а мне в конкуррентном коде на Go ни разу не захотелось использовать panic, например. P.S. Вообще, мы тут сильно отвлекаемся от темы, как бы нас в холивары не перекинули. =) |
Сообщ.
#120
,
|
|
|
Цитата korvin @ Вообще, мы тут сильно отвлекаемся от темы, как бы нас в холивары не перекинули. =) Слона то ты и не заметил |
Сообщ.
#121
,
|
|
|
Цитата korvin @ Никуда они не открепляются. Всегда кто-то ждет завершения этой корутины, аварйино или нормально. Это может быть планировщик или еще что-нибудь.В этом смысл корутин, после вызова они «открепляются» от вызвавшей/создавшей их сущности и живут сами по себе. А планировщик, например, может быть встроен в рантайм и недоступен из языка. Цитата korvin @ Это на случай если никто не позаботился об обработке этого исключения. Что еще с ним делать, если смерть несчастной корутины никого не волнует даже того, кто собственно ее породил?2) Нормальный ход. Т.е. исключение просто уйдёт в никуда? Чем это отличается от простого return? Цитата korvin @ Ты сам-то понял что сказал в этой фразе? Я имел ввиду http-сервер работающий на корутинах. Пришел http-запрос извне, запускаем корутину для работы с этим запросом, она внезапно сдохла выбросив исключение. http-сервер поймал это исключение обработал его и выдал соответствующую HTTP-ошибку в TCP-сокет. Где тут "трудности"?3) «И что?» В протоколе HTTP нет исключений, только коды ошибок. Ты (ну или билиотечная функция) получаешь от HTTP-сервера код ошибки, оборачивает его в исключение, ты (уже в своём коде) его отлавливаешь и передаешь дальше по HTTP код ошибки. Создал себе трудность и героически её преодолел, молодец, чё. =) Цитата korvin @ Да, но на основании этого нельзя утверждать, что исключения плохи в конкурентном коде. Я же не утверждаю, что в конкурентном коде нельзя обойтись без исключений.4) Молодец какой, а мне в конкуррентном коде на Go ни разу не захотелось использовать panic, например. Цитата korvin @ Уже перекинули, если ты не заметил P.S. Вообще, мы тут сильно отвлекаемся от темы, как бы нас в холивары не перекинули. =) |
Сообщ.
#122
,
|
|
|
Цитата MyNameIsIgor @ В случае акторов, то в том же Erlang есть дереве наблюдения процессов, и мы можем отлавливать ошибки других процессов. Ага, и с исключениями там тот ещё бардак. Цитата There should really be a compiler warning - ** try-catch-after used - this is probably not the right way to do things Cheers |
Сообщ.
#123
,
|
|
|
Цитата korvin @ Ага, и с исключениями там тот ещё бардак. Ну, грубо говоря, там два механизма - старый и новый. И оба не рекомендуются к использованию В пользу концепции let it crash. |
Сообщ.
#124
,
|
|
|
Цитата MyNameIsIgor @ Слона то ты и не заметил Черт, я пока набирал сообщение, подумал, надо посмотреть, с чего всё началось и вернуться к теме, а ссылок на предыдущие страницы-то нет. Не сразу понял, что за фигня. =) Добавлено Цитата MyNameIsIgor @ Ну, грубо говоря, там два механизма - старый и новый. И оба не рекомендуются к использованию В пользу концепции let it crash. Ну как рекомендации по использованию panic в Go. О чём и речь. |
Сообщ.
#125
,
|
|
|
Цитата korvin @ Ну как рекомендации по использованию panic в Go. О чём и речь. Нет, речь о том, что ты спрашивал, кто перехватит исключение из сопрограммы. В Erlang я могу получить сообщение о падении другого процесса и обработать его, не завершая программу. В Go я могу в одной горутине обработать панику другой горутины? |
Сообщ.
#126
,
|
|
|
Цитата applegame @ 1) Никуда они не открепляются. Всегда кто-то ждет завершения этой корутины, аварйино или нормально. Это может быть планировщик или еще что-нибудь. 2) Это на случай если никто не позаботился об обработке этого исключения. Что еще с ним делать, если смерть несчастной корутины никого не волнует даже того, кто собственно ее породил? 3) Ты сам-то понял что сказал в этой фразе? Я имел ввиду http-сервер работающий на корутинах. Пришел http-запрос извне, запускаем корутину для работы с этим запросом, она внезапно сдохла выбросив исключение. http-сервер поймал это исключение обработал его и выдал соответствующую HTTP-ошибку в TCP-сокет. Где тут "трудности"? 4) Да, но на основании этого нельзя утверждать, что исключения плохи в конкурентном коде. Я же не утверждаю, что в конкурентном коде нельзя обойтись без исключений. 1) На уровне языка никто не ждёт. Если я запущу долгую корутину, а потом выйду из main, программа тупо завершится. Со всеми корутинами. Чтобы ждать, мне придётся воспользоваться пакетом sync например, или вручную организовать ожидание. 2) Т.е. ошибка прошла незамеченой. Хороший подход. Видимо, BSOD из таких: все наплевали, а результат в итоге «на экран». 3) Каким образом именно HTTP сервер её поймает? Откуда он знает, что это исключение предназначалось ему, а не какой-то другой корутине, которая, например, разруливает запросы к БД? Если у меня две корутины, отлавливающие исключения, которая из них должна поймать это исключение? Если запрос запустил корутину и корректно завершился (т.к. ему пофиг на корутину, она просто в фоне должна что-то делать), соединение с клиентом закрылось, куда HTTP сервер отправит ошибку? 4) Там по ссылке подробней. Добавлено Цитата MyNameIsIgor @ В Erlang я могу получить сообщение о падении другого процесса и обработать его, не завершая программу. В Go я могу в одной горутине обработать панику другой горутины? Нет. Горутины взаимодействуют только через каналы. Но, раз в Эрланге можно, если у меня два процесса мониторят один, какой из них перехватит исключение? Как вообще передаются исключения? |
Сообщ.
#127
,
|
|
|
Цитата korvin @ Но, раз в Эрланге можно, если у меня два процесса мониторят один, какой из них перехватит исключение? Как вообще передаются исключения? Получат оба. И не совсем исключение, а сигнал о завершении, исключения используются (вернее, не рекомендуются к использованию) внутри процесса. Лучше прочитай здесь. |
Сообщ.
#128
,
|
|
|
Цитата OpenGL @ Цитата Qraizer @ Теперь ещё и злостный оффтоп. Скрытый текст Мы уже морально были готовы к переносу Скрытый текст Т.е. никто даже не сомневался, что банки не будет. А я всё-таки раздумывал, ибо калечить тему не хотелось. |
Сообщ.
#129
,
|
|
|
Цитата MyNameIsIgor @ Получат оба. И не совсем исключение, а сигнал о завершении. Таки чем это отличается от отправки сообщения по каналу? |
Сообщ.
#130
,
|
|
|
Цитата korvin @ Таки чем это отличается от отправки сообщения по каналу? Таки ничем. Но разговор то у нас об обработке падения сопрограммы. Ты задавал вопрос - кто же будет обрабатывать? Вот я и отвечаю - найдётся кто. В чём проблема то? |
Сообщ.
#131
,
|
|
|
Цитата korvin @ В этом случае никто не ждет, но это бессмысленный случай. Зачем запускать корутину, чтобы не дожидаясь ее просто выйти из main?На уровне языка никто не ждёт. Если я запущу долгую корутину, а потом выйду из main, программа тупо завершится. Со всеми корутинами. Чтобы ждать, мне придётся воспользоваться пакетом sync например, или вручную организовать ожидание. Цитата korvin @ Да, плохой подход. Но это если все через жопу написано. В нормальных системах планировщик перехватит такое исключение. Никаких BSODов, приложение продолжит работать.2) Т.е. ошибка прошла незамеченой. Хороший подход. Видимо, BSOD из таких: все наплевали, а результат в итоге «на экран». Цитата korvin @ Все просто, HTTP-сервер создал корутину и выполняет в ней пользовательский обработчик запроса. Этот пользовательский обработчик завернут в try/catch (в HTTP сервере), все исключения произошедшие в нем будут пойманы и обработаны. Про корутину разруливающую запросы к БД не совсем понял. Если пользовательский обработчик создал еще какие-то корутины и не обработал их исключения, то они упадут и исключения попадут уже не к HTTP-серверу, а выше - к планировщику.Каким образом именно HTTP сервер её поймает? Откуда он знает, что это исключение предназначалось ему, а не какой-то другой корутине, которая, например, разруливает запросы к БД? Цитата korvin @ Исключения бросают из вызываемых функций, очевидно что тут нет понятия "должна", исключения "может" ловить только та корутина, которая эту функцию запустила (прямо или вложенно через другие функции). Исключение либо ловится на каком либо уровне внутри корутины либо вылезает за ее пределы корутины к планировщику.Если у меня две корутины, отлавливающие исключения, которая из них должна поймать это исключение? Цитата korvin @ Зачем HTTP-серверу отправлять ошибку, если обработчик запросов завершился корректно? Отправит клиенту 200 Ok. А фоновая корутина будет работать сама по себе, а ее исключения ловятся либо ей самой либо опять же планировщиком.Если запрос запустил корутину и корректно завершился (т.к. ему пофиг на корутину, она просто в фоне должна что-то делать), соединение с клиентом закрылось, куда HTTP сервер отправит ошибку? P.S. У меня создается впечатление, что мы с тобой о разных сущностях говорим. |
Сообщ.
#132
,
|
|
|
Цитата OpenGL @ ЕМНИП, только в дебаге. Ну да, наверное. Цель же - указать на неправильное использование. Цитата OpenGL @ Если сверх тех ограничений, что заложены в язык, надо дополнительно оговаривать, когда можно, а когда нельзя применять исключения в данной библиотеке, то говорить о поддержке исключений в ней, имхо, неверно. Дык, никто не мешает писать код не задумываясь об "exception safety". И С++ не предоставляет не предоставляет никаких средств, чтобы указать на это, кроме документирования. Qt тут ничем не хуже и не лучше той же стандартной библиотеки - если сырые указатели в вектор положить, то память легко утечь может. Имхо, как раз всё укладывается в "ограничения языка". |
Сообщ.
#133
,
|
|
|
Цитата MyNameIsIgor @ Таки ничем. Но разговор то у нас об обработке падения сопрограммы. Ты задавал вопрос - кто же будет обрабатывать? Вот я и отвечаю - найдётся кто. В чём проблема то? В том, что этот кто может быть не один? И может оказаться неизвестно где? Как отладчику с этим работать? |
Сообщ.
#134
,
|
|
|
Цитата korvin @ Цитата MyNameIsIgor @ Таки ничем. Но разговор то у нас об обработке падения сопрограммы. Ты задавал вопрос - кто же будет обрабатывать? Вот я и отвечаю - найдётся кто. В чём проблема то? В том, что этот кто может быть не один? И может оказаться неизвестно где? Как отладчику с этим работать? Брать и работать... ЕМНИП, отладчики Erlang позволяют посмотреть кто кого мониторит, кто с кем связан и т.п. Вообще, это не такая большая проблема по сравнению с завершением программы по панике. Кто-то в используемой мной библиотеке захочет попаниковать. И вот как мне, программисту, это лечить? |
Сообщ.
#135
,
|
|
|
Народ, а вообще есть хоть какая инфа, почему разработчики Qt напрочь отказались от обработки исключений в своем коде?
|
Сообщ.
#136
,
|
|
|
Цитата applegame @ 1) В этом случае никто не ждет, но это бессмысленный случай. Зачем запускать корутину, чтобы не дожидаясь ее просто выйти из main? 2) Все просто, HTTP-сервер создал корутину и выполняет в ней пользовательский обработчик запроса. Этот пользовательский обработчик завернут в try/catch (в HTTP сервере), все исключения произошедшие в нем будут пойманы и обработаны. Про корутину разруливающую запросы к БД не совсем понял. Если пользовательский обработчик создал еще какие-то корутины и не обработал их исключения, то они упадут и исключения попадут уже не к HTTP-серверу, а выше - к планировщику. 3) Исключения бросают из вызываемых функций, очевидно что тут нет понятия "должна", исключения "может" ловить только та корутина, которая эту функцию запустила (прямо или вложенно через другие функции). Исключение либо ловится на каком либо уровне внутри корутины либо вылезает за ее пределы корутины к планировщику. 4) Зачем HTTP-серверу отправлять ошибку, если обработчик запросов завершился корректно? Отправит клиенту 200 Ok. А фоновая корутина будет работать сама по себе, а ее исключения ловятся либо ей самой либо опять же планировщиком. 1) Это для примера того, что выполнение корутины не зависит от корутины, породившей её. 2) В этой корутине я создал другую корутину, выполняющую фоновый бекап, например, и вернул код 200 или какой там HTTP OK, чтобы клиент не ждал 100500 часов завершения бэкапа и вообще получения ответа, а увидел, что задание запущено. При func foo() { try { doSomething() } catch (err) { handleError(err) } } foo ждёт завершения doSomething или выброса её исключения. При func foo() { try { go doSomething() } catch (err) handleError(err) } } foo не может ждать, она запустила горутину и завершилась. В этом смысл корутин, чтобы не ждать. Иначе второй код ничем не отличался бы от первого. 3) Да речь не об этом. Речь о выбросе исключения из самой корутины. См. пункт 2. 4) И дальше что? Планировщик только распределяет выполнение инструкций, ну, допустим, он поймал исключение, как ты сообщишь клиенту об этом, если он давно отвалился. Может, он вообще больше никогда не подключится. Как вообще должна выглядеть синтаксически обработка исключений от корутин? Вот см. пункт 2. Как должна работать процедура foo? Добавлено Цитата MyNameIsIgor @ Брать и работать... ЕМНИП, отладчики Erlang позволяют посмотреть кто кого мониторит, кто с кем связан и т.п. Вообще, это не такая большая проблема по сравнению с завершением программы по панике. Кто-то в используемой мной библиотеке захочет попаниковать. И вот как мне, программисту, это лечить? Тебе, в общем случае, никак. Проверить свой код, что ты используешь библиотеку правильно, если твоих косяков нет, написать багрепорт автору библиотеки. Если она опенсорсная, можешь попробовать сам исправить баг и отослать патч. А городить костыли-обертки из исключений над кривым кодом не нужно. |
Сообщ.
#137
,
|
|
|
Цитата korvin @ А городить костыли-обертки из исключений над кривым кодом не нужно Знаешь, говорил я как-то с одним плюсовиком, написавшим класс мьютекса с assert на случай, если ОС ему мьютекс не создала. Ну, вот утверждает он мне, что надо падать - и всё тут. На мои вопросы вроде "а если я этот мьютекс в плагине использую?" никакого внятного ответа не получил. Так и не убедил кидать исключение. Я к чему. Падать или нет - это мне решать. У других могут быть другие взгляды. Так же получится и с паникой. Дело не в костылях, а в том, что я хочу решать. И если мне этого не дают, то нафиг-нафиг. |
Сообщ.
#138
,
|
|
|
Исключения может и не идеально, но все остальное ещё хуже. В каком-то отдельном проекте может быть смысл отказа от них, но на уровне языка это явно неверно.
|
Сообщ.
#139
,
|
|
|
korvin
Цитата korvin @ Зависит на самом деле. Корутина сама по себе работать не будет. Это не поток. Но можно ее отдать планировщику и он сам уже будет ее крутить.Это для примера того, что выполнение корутины не зависит от корутины, породившей её. Цитата korvin @ Я вообще-то говорил о запуске пользовательского обработчика, а не дополнительной корутины, то что ты написал в первом примере.2) В этой корутине я создал другую корутину... Я не знаю как там в горутинах, а в корутинах вот так void foo() { ... auto fiber = new Fiber(&worker); // корутина еще не работает auto e = fiber.call(); // корутина крутится пока не вызван yield(); // сюда управление не дойдет до тех пор // пока внутри worker не будет вызван yield(); ... } Цитата korvin @ Я не пойму что ты хочешь мне этим сказать? Как тебе поможет в данном случае отказ от исключений? Полагаю, что то что ты тут у меня спрашиваешь вообще ортогонально к исключениям. 3) Да речь не об этом. Речь о выбросе исключения из самой корутины. См. пункт 2. 4) И дальше что? Планировщик только распределяет выполнение инструкций, ну, допустим, он поймал исключение, как ты сообщишь клиенту об этом, если он давно отвалился. Может, он вообще больше никогда не подключится. Как вообще должна выглядеть синтаксически обработка исключений от корутин? Вот см. пункт 2. Как должна работать процедура foo? Добавлено Цитата applegame @ Для D это выглядит вот так:Как вообще должна выглядеть синтаксически обработка исключений от корутин? auto e = fiber.call(); if(e) { writefln("корутина сдохла: %s", e.msg); } я надеюсь ты в курсе, что корутины сами по себе не работают? На то они и корутины. Тебе нужно периодически вызывать Fiber.call(), а внутри корутины соответственно Fiber.yield(). |
Сообщ.
#140
,
|
|
|
Цитата JoeUser @ Народ, а вообще есть хоть какая инфа, почему разработчики Qt напрочь отказались от обработки исключений в своем коде? Обычно цитируют вот это: Цитата When Qt was started exceptions were not available for all the compilers that needed to be supported by Qt. Today we are trying to keep the APIs consistent, so modules that have a history of not using exceptions will generally not get new code using exceptions added. You will notice exceptions are used in some of the new modules of Qt. Правда ссылки, которые приводят, уже протухли. Ну и для "базового апи" это вполне удобно, имхо. А дальше мы уже сами решаем является та или иная ошибка "исключительной ситуацией". Ещё удобнее, конечно, предоставлять по две версии (ну или с перегрузкой) апи, но это, очевидно, больше работы потребует. |
Сообщ.
#141
,
|
|
|
Почитал я про горутины и сдается мне что korvin путает горутины и корутины, а это разные вещи на самом деле. Горутина - это фактически надстройка над корутинами, причем горутины подразумевают наличие планировщика, который, как я понимаю, встроен в Go.
Аналог горутин в vibe.d - это Task: void foo() { Task[] pool; // стартуем параллельно три таска и пишем их в массив iota(3).each!(i => pool ~= runTask({ // тельце корутины, передача управления другим корутинам в этом потоке // только при блокирующих операциях (I/O, мьютексы и прочая байда) ... veryLongRequest(i); ... }) ); // ждем пока все таски не выполнятся pool.each!(t => t.join); } |
Сообщ.
#142
,
|
|
|
Я тут по нужде написал на java програмулину.
Ну, что то она там из оракла выдергивает, и т.п. JDBC и все такое. Написал быстро и был доволен. До поры. Пока мне не пришлось обработать более 1200 селектов за сессию. А далье меня обругали - что слишком много курсоров в сессии. ОКАЗЫВАЕТСЯ РЕКОРДСЕТЫ НАДО ЗАКРЫВАТЬ ВРУЧНУЮ! Фу!! Каменный век! я в C++ не помню когда последний раз использовал close() или delete вручную, все закрывается само - в деструкторе. Авто-объекты рулят. И кто после этого язык с автоматической сборкой мусора??? неужели JAVA??? |
Сообщ.
#143
,
|
|
|
Автоматическая и автоматизированная – разные вещи. И – да: я за вторую.
|
Сообщ.
#144
,
|
|
|
Цитата Бобёр @ Я тут по нужде написал на java програмулину. Ну, что то она там из оракла выдергивает, и т.п. JDBC и все такое. Написал быстро и был доволен. До поры. Пока мне не пришлось обработать более 1200 селектов за сессию. А далье меня обругали - что слишком много курсоров в сессии. ОКАЗЫВАЕТСЯ РЕКОРДСЕТЫ НАДО ЗАКРЫВАТЬ ВРУЧНУЮ! Фу!! Каменный век! я в C++ не помню когда последний раз использовал close() или delete вручную, все закрывается само - в деструкторе. Авто-объекты рулят. И кто после этого язык с автоматической сборкой мусора??? неужели JAVA??? А с try-with-resources эта штука не работает? |
Сообщ.
#145
,
|
|
|
Ну, очевидно же, да? что я close() в секцию finally записал.
А есть ли какой то аналог C#-ого using или питонячьего with в java? |
Сообщ.
#146
,
|
|
|
Цитата Бобёр @ Ну, очевидно же, да? что я close() в секцию finally записал. А есть ли какой то аналог C#-ого using или питонячьего with в java? Так я про этот аналог и говорил в прошлом посте The try-with-resources Statement |
Сообщ.
#147
,
|
|
|
А.. вон оно что, Михалыч
а оно закрывает, да? будем юзать. |
Сообщ.
#148
,
|
|
|
Цитата Бобёр @ все закрывается само - в деструкторе так деструкторов-то нет! отсюда вся печаль |
Сообщ.
#149
,
|
|
|
Ну так какие могут быть деструкторы в случае сборки мусора? Только финализаторы.
|
Сообщ.
#150
,
|
|
|
ну, финализатор это совсем не то. Мягко говоря , нежно выражаясь
|
Сообщ.
#151
,
|
|
|
Ага. Вот только деструкторы со сборкой не дружат, так что альтернативы нет...
Так чем тебе не нравится try-with-resources/using? |
Сообщ.
#152
,
|
|
|
Цитата D_KEY @ Ага. Вот только деструкторы со сборкой не дружат, так что альтернативы нет... Чисто теоретически - почему нельзя сделать вызов деструкторов обязательным при выходе из области видимости переменной? Вроде как должно быть удобно. |
Сообщ.
#153
,
|
|
|
Цитата OpenGL @ Цитата D_KEY @ Ага. Вот только деструкторы со сборкой не дружат, так что альтернативы нет... Чисто теоретически - почему нельзя сделать вызов деструкторов обязательным при выходе из области видимости переменной? Вроде как должно быть удобно. Если у тебя нет объектов на стеке в языке, то это не так уж и просто. |
Сообщ.
#154
,
|
|
|
Да ладно - компилятор знает всё о локальных объектах в момент компиляции. Что ещё нужно?
|
Сообщ.
#155
,
|
|
|
Цитата negram @ Да ладно - компилятор знает всё о локальных объектах в момент компиляции. Что ещё нужно? Понять, что делать с кодом, который передаёт наш объект в какой-то метод, например. Сохраняется ли там ссылка на объект? Компилятор в общем случае это знать не может. Я уже не говорю о мультитредности. Не очень понятно, что делать и в более прозрачном случае, когда мы сохраняем объект в переменную охватывающей области видимости. Или в поле другого объекта. |
Сообщ.
#156
,
|
|
|
Цитата D_KEY @ Так чем тебе не нравится try-with-resources/using? Тем, что об этом должен знать пользовательский код? "Забыть вызвать деструктор" несколько сложнее. Опять же, в плюсах ты можешь в своём классе иметь данные, которые владеют ресурсами. При этом пользователю ничего дополнительно знать не надо. А со всякими try-with-resources, если внутри класса появляется ресурс, то надо править места, где класс используется. |
Сообщ.
#157
,
|
|
|
Цитата D_KEY @ Понять, что делать с кодом, который передаёт наш объект в какой-то метод, например. Сохраняется ли там ссылка на объект? Компилятор в общем случае это знать не может. Можно, например, со счётчиком ссылок это совместить. Кстати, если в шарпе открыть файл/подключение/etc, и потерять ссылку на объект - финализатор даже по истечении времени не вызовется? |
Сообщ.
#158
,
|
|
|
Цитата OpenGL @ Можно, например, со счётчиком ссылок это совместить. ну это то же самое, что освобождать ресурс в финализаторе |
Сообщ.
#159
,
|
|
|
Цитата DarkEld3r @ Цитата D_KEY @ Так чем тебе не нравится try-with-resources/using? Тем, что об этом должен знать пользовательский код? "Забыть вызвать деструктор" несколько сложнее. Опять же, в плюсах ты можешь в своём классе иметь данные, которые владеют ресурсами. При этом пользователю ничего дополнительно знать не надо. А со всякими try-with-resources, если внутри класса появляется ресурс, то надо править места, где класс используется. Забыть, условно, free - просто. Забыть открыть файл или получить другой ресурс сложнее Не подумать о том, что ты открываешь ресурс тоже сложно. Что касается полей в классе, то ты просто делаешь свой объект совместимым с тем же механизмом и возлагаешь ответственность на вызывающий код.ф Добавлено Цитата OpenGL @ Цитата D_KEY @ Понять, что делать с кодом, который передаёт наш объект в какой-то метод, например. Сохраняется ли там ссылка на объект? Компилятор в общем случае это знать не может. Можно, например, со счётчиком ссылок это совместить. С каким счётчиком ссылок? Добавлено Цитата wind @ Цитата OpenGL @ Можно, например, со счётчиком ссылок это совместить. ну это то же самое, что освобождать ресурс в финализаторе Нет. Финализатор когда вызовется, да и вызовется ли вообще - неизвестно. А счётчик ссылок даёт нам детерминированное время вызова. Как только 0, так сразу. |
Сообщ.
#160
,
|
|
|
Цитата D_KEY @ С каким счётчиком ссылок? С тем, который можно добавить при реализации этих деструкторов в языке |
Сообщ.
#161
,
|
|
|
Цитата OpenGL @ Цитата D_KEY @ С каким счётчиком ссылок? С тем, который можно добавить при реализации этих деструкторов в языке И тут вылазит радость: сборка мусора быстрее, чем счётчики ссылок, которые ещё и циклами чреваты. Да, она имеет привычку "тормозить мир", а счётчики равномерно размазаны по программе, но они медленные. |
Сообщ.
#162
,
|
|
|
Цитата D_KEY @ Что касается полей в классе, то ты просто делаешь свой объект совместимым с тем же механизмом и возлагаешь ответственность на вызывающий код.ф Ну так я об этом и говорю. Вопрос был - "чем не нравятся try-with-resources/using". Ответ - тем, что пользовательскому коду надо знать про детали реализации. В плюсах, если я после рефакторинга добавил классу владение каким-либо ресурсом, пользовательский код менять не надо. А если у нас нет деструкторов, то безболезненно такие вещи не пройдут. |
Сообщ.
#163
,
|
|
|
Цитата OpenGL @ Цитата D_KEY @ С каким счётчиком ссылок? С тем, который можно добавить при реализации этих деструкторов в языке Ага... Т.е. ссылки иногда будут просто ссылками(и тогда GC), а иногда для них ведётся подсчет ссылок? А типы это будут другие? Сможем наследоваться от класса с деструтором? Сможем породить от "обычного" класса класс с деструктором? Сможем сделать поле класса с деструктором? Сможем в классе с деструктором сделать поле "обычного" класса? Как будем бороться с циклическими ссылками? Разрешим ли сборщику удалять группы зацикленных объектов? Разрешим ли переключение из режима вызова деструктора в обычный стиль с using/with? Добавлено Цитата DarkEld3r @ Вопрос был - "чем не нравятся try-with-resources/using". Ответ - тем, что пользовательскому коду надо знать про детали реализации. Это не вопрос реализации... Может пример? |
Сообщ.
#164
,
|
|
|
Цитата D_KEY @ Это не вопрос реализации... Может пример? Да как-то так: var a = new SomeClass(); a.someMethod(); Потом в классе появляется поле владеющее ресурсом - в итоге код перестаёт быть корректным и надо его переделывать в: using (var a = new SomeClass()) { a.someMethod(); } При этом клиентам, вероятно, вообще не надо знать, что я там использую внутри. В С++, благодаря деструкторам, ничего менять не пришлось. Да, там тоже можно сделать new SomeClass и не позвать delete, но это уже другая проблема и с владением ресурсами она не связана. Да, я понимаю, что с ГЦ иначе и не сделать, но удобным оно от этого быть не начинает. |
Сообщ.
#165
,
|
|
|
Мне почему-то кажется, что тут в большинстве случаев можно изолировать использование ресурса внутри метода... Иначе бы SomeClass изначально воспринимался как ресурс.
Впрочем допускаю, что иногда это неудобно. |
Сообщ.
#166
,
|
|
|
Цитата DarkEld3r @ При этом клиентам, вероятно, вообще не надо знать, что я там использую внутри. Это вообще вопрос уровня API. При работе с ресурсами хочет пользователь знать или не очень, а придется. А тот кому не надо, использует API уровня Чудо.сотворись(). |
Сообщ.
#167
,
|
|
|
Цитата wind @ Это вообще вопрос уровня API. При работе с ресурсами хочет пользователь знать или не очень, а придется А зачем? В C++ это вполне может быть делом класса, клиенту это знать не нужно. |
Сообщ.
#168
,
|
|
|
Цитата D_KEY @ В C++ это вполне может быть делом класса, клиенту это знать не нужно. ну то есть когда я пишу пул соединений или пул потоков, то мне не интересно когда и как они закрываются? |
Сообщ.
#169
,
|
|
|
Цитата wind @ ну то есть когда я пишу пул соединений или пул потоков, то мне не интересно когда и как они закрываются? Взял из пула, вернул в пул(автоматически, через подсчет ссылок), что тебе ещё нужно знать? |
Сообщ.
#170
,
|
|
|
Цитата D_KEY @ Взял из пула, вернул в пул Я говорил "пишу", а не "использую". Если я использую класс, представляющий ресурс, я принципиально не могу не знать, что его нужно освобождать. Здорово, если для этого не нужно много телодвижений. Добавлено Цитата D_KEY @ Взял из пула, вернул в пул Хотя тут та же самая ситуация. Я должен точно знать, когда оно возвращается в пул, что я для этого должен сделать, не могу не знать. |
Сообщ.
#171
,
|
|
|
Цитата wind @ Хотя тут та же самая ситуация. Я должен точно знать, когда оно возвращается в пул, что я для этого должен сделать, не могу не знать. Да легко можно не знать. На C++ void foo() { auto connection = pool.get(); connection.exec("delete from idiots"); } Что там в деструкторе connection происходит - не моё дело. |
Сообщ.
#172
,
|
|
|
Цитата MyNameIsIgor @ Да легко можно не знать. Нельзя не знать контракта класса, который ты используешь. А приведенный тобой пример как раз ярко иллюстрирует тот факт, что метод принадлежит вовсе не классу, представляющему ресурс, и в этом случае тебе действительно не нужно знать, каким образом и с какими ресурсами он связан. |
Сообщ.
#173
,
|
|
|
Цитата wind @ Нельзя не знать контракта класса, который ты используешь. А приведенный тобой пример как раз ярко иллюстрирует тот факт, что метод принадлежит вовсе не классу, представляющему ресурс, и в этом случае тебе действительно не нужно знать, каким образом и с какими ресурсами он связан. При чём тут контракт класса? Допустим, у нас имеется некоторый класс-хранилище (Cache) объектов в памяти и такой клиентский код: void foo() { Cache c; // do many actions with cached objects } Теперь мы хотим, чтобы кэш куда-то сохранялся в промежутке между вызовами foo. Мы дописываем соответствующие действия сохранения и восстановления в деструктор и конструктор Cache соответственно и оно работает без изменения кода foo. И foo вообще не нужно знать, как внутри устроен объект класса Cache, сохраняет он что-то куда-то (в более постоянное место в памяти, БД, файлы, в т.ч. и сетевые) или нет. Абстракция, ООП. В случае с языком с GC, нам нужно явно вызывать какой-нибудь метод Cache::close(), которого могло не быть в изначальном интерфейсе класса Cache, и соответственно не быть его вызова в foo, ведь в начале предполагалось, что Cache хранит свои объекты просто в (своей) памяти, которая становится не нужна после выхода из foo, а следовательно и нечего о ней заботится, GC почистит. А вот транзакцию / сетевое соединение он так не закроет сам. |
Сообщ.
#174
,
|
|
|
Цитата korvin @ Теперь мы хотим, чтобы кэш куда-то сохранялся в промежутке между вызовами foo. Мы дописываем соответствующие действия сохранения и восстановления в деструктор и конструктор Cache соответственно и оно работает без изменения кода foo. И не работает, если объект поселили в статическую переменную и не разрушают никогда. Да, можно и шарики себе, в принципе, отстрелить, но такие экстремальные отклонения не рассматриваются. Ты, скорее всего не будешь оставлять "висящие" ресурсы в коде, который ты понятия не имеешь как используют и будешь расширять класс, о котором знают - его инстанс в обязательном порядке надо грохнуть/закрыть после использования. |
Сообщ.
#175
,
|
|
|
Цитата wind @ И не работает, если объект поселили в статическую переменную и не разрушают никогда Так и не предполагалось, что будет работать. Написано же Цитата korvin @ Теперь мы хотим, чтобы кэш куда-то сохранялся в промежутке между вызовами foo. А если вы сами сделали переменную неразрушаемой, то и смысла нет сохранять её состояние. А вот о чём мы тут говорим: в Java/C#/Python и подобном при таком изменении Cache пришлось бы менять код foo для использования конструкций try-with-resource/using/with и подобное. Добавлено Цитата wind @ знают - его инстанс в обязательном порядке надо грохнуть/закрыть после использования Вы не улавливаете суть. Дело в том, что в C++ все экземпляры надо "грохнуть/закрыть после использования". В языках же со сборкой мусора появляется двойственность: объекты, которые потребляют только ресурс "память", грохаются автоматически; а объекты, использующие какие-то ещё ресурсы, надо грохать руками. |
Сообщ.
#176
,
|
|
|
Цитата wind @ Если я использую класс, представляющий ресурс, я принципиально не могу не знать, что его нужно освобождать. Почему? A a = ...; a это ресурс или нет? Если нет, то что изменится, если a станет ресурсом? |
Сообщ.
#177
,
|
|
|
Цитата wind @ 1) И не работает, если объект поселили в статическую переменную и не разрушают никогда. 2) Да, можно и шарики себе, в принципе, отстрелить, но такие экстремальные отклонения не рассматриваются. 3) Ты, скорее всего не будешь оставлять "висящие" ресурсы в коде 4) который ты понятия не имеешь как используют и будешь расширять класс, о котором знают 5) его инстанс в обязательном порядке надо грохнуть/закрыть после использования. 1) А если бабушке пришить... Ну ты понял. 2) Так никто и не рассматривает, приведённый мной пример вполне банален, типичен, «мейнстримен» для C++, никаких отклонений, тем более экстремальных, а ситуация вполне типична для любого ЯП. 3) В примере нет никаких «висящих» ресурсов, что бы это не значило. 4) Я имею право расширять/модифицировать класс как угодно, если это не нарушает его инвариантов (как раз в моём примере никакого нарушения нет), а в общем случае — не меняет его интерфейс. Ибо знают только интерфейс. В этом суть ООП, в знании только интерфейса и полагаться только на интерфейс. 5) Он и так грохается обязательно. Автоматически. Правило симметрии вполне работает: конструктор — захват, деструктор — освобождение. Добавлено Цитата MyNameIsIgor @ В языках же со сборкой мусора появляется двойственность: объекты, которые потребляют только ресурс "память", грохаются автоматически; а объекты, использующие какие-то ещё ресурсы, надо грохать руками. Это компромисс: «объекты, использующие только память» почти всегда количественно преобладают над остальными ресурсами, при чём, обычно, существенно. |
Сообщ.
#178
,
|
|
|
Цитата D_KEY @ a это ресурс или нет? Если нет, то что изменится, если a станет ресурсом? Я должен буду знать, что его нужно как-нибудь побыстрее освободить, капитан. |
Сообщ.
#179
,
|
|
|
Цитата wind @ Цитата D_KEY @ a это ресурс или нет? Если нет, то что изменится, если a станет ресурсом? Я должен буду знать, что его нужно как-нибудь побыстрее освободить, капитан. Зачем? Что значит побыстрее? А обычные объекты ты держишь подольше? Зачем? |
Сообщ.
#180
,
|
|
|
Цитата D_KEY @ Зачем? Что значит побыстрее? А обычные объекты ты держишь подольше? Зачем? Затем чтобы не отковыривать проблемы через месяцы/годы после сдачи проекта. Ты наверняка читал или слушал, например, общие рекомендации (за авторством любого опытного специалиста) при работе с транзакциями в СУБД. Вот воспроизведи про себя. |
Сообщ.
#181
,
|
|
|
Цитата wind @ Цитата D_KEY @ Зачем? Что значит побыстрее? А обычные объекты ты держишь подольше? Зачем? Затем чтобы не отковыривать проблемы через месяцы/годы после сдачи проекта Ты можешь быть более конкретным? |
Сообщ.
#182
,
|
|
|
Цитата wind @ Цитата D_KEY @ a это ресурс или нет? Если нет, то что изменится, если a станет ресурсом? Я должен буду знать, что его нужно как-нибудь побыстрее освободить, капитан. При детерминированном уничтожении объектов все они живут ровно столько, сколько в них есть необходимость. Ещё раз говорю - неопределённость возникает именно при сборщике мусора, которые за ресурсом "память" следит по-особому. В C++ за памятью следят точно так же, как и за файлами и соединениями с БД. Потому, если какой-то класс помимо памяти ещё и открывает файл, это не приводит к изменению кода, который его использует. |
Сообщ.
#183
,
|
|
|
Цитата wind @ Цитата D_KEY @ a это ресурс или нет? Если нет, то что изменится, если a станет ресурсом? Я должен буду знать, что его нужно как-нибудь побыстрее освободить, капитан. Так ты кодом покажи. Что изменится? |
Сообщ.
#184
,
|
|
|
Цитата JoeUser @ "в Цэ++ уже давно есть множественное наследование, а в таких языках как Джава и .NET их нет, в 8-ой есть, хотя не такой как в С++ public class MyClass implements InterfaceA, InterfaceB { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here } @Override public void saySomething() { System.out.println("Hello World"); } @Override public void sayHi() { InterfaceA.super.sayHi(); } } interface InterfaceA { public void saySomething(); default public void sayHi() { System.out.println("Hi from InterfaceA"); } } interface InterfaceB { default public void sayHi() { System.out.println("Hi from InterfaceB"); } } |
Сообщ.
#185
,
|
|
|
Наследование интерфейсов было всегда. В 8ой яве добавили реализацию методов интерфейсов по умолчанию.
|
Сообщ.
#186
,
|
|
|
Кстати, про финализаторы (в Java, но, думаю, в какой-то степени, это и к C# относится).
|
Сообщ.
#187
,
|
|
|
Объясните мне накой писать в C++ проекте 2015 года такое говно?
typedef signed short СXShort; typedef unsigned short СXUShort; typedef signed int СXInt; ... Вот это волшебство я вообще не осиливаю. #define СX_TRUE true #define СX_FALSE false Как будто вернулся в девяностые. |
Сообщ.
#188
,
|
|
|
это для переносимости я так думаю. Правда, true и false - это слишком
|
Сообщ.
#189
,
|
|
|
Цитата applegame @ Не может быть, чтобы там были "точка с запятой" в конце строки! Или неужто на самом деле есть? Вот это волшебство я вообще не осиливаю. |
Сообщ.
#190
,
|
|
|
я так понимаю там тоже typedef.
|
Сообщ.
#191
,
|
|
|
Цитата Бобёр @ А как именно вы понимаете? Так? :я так понимаю там тоже typedef. typedef true CX_TRUE; |
Сообщ.
#192
,
|
|
|
Цитата Славян @ Нет точек с запятой там нет, исправил. Не может быть, чтобы там были "точка с запятой" в конце строки! Или неужто на самом деле есть? Добавлено Цитата Бобёр @ Для какой переносимости? Это же встроенные типы, они переносимы по определению. это для переносимости я так думаю. Правда, true и false - это слишком Добавлено И еще эти убогие префиксы CX. Для кого неймспейсы придуманы? |
Сообщ.
#193
,
|
|
|
Цитата applegame @ Для ++ного случая, а так - вроде как чистая Си'шность сохранена. Для кого неймспейсы придуманы? |
Сообщ.
#194
,
|
|
|
Например, порт проекта на старый компиль.
Добавлено Или на недокомпиль для микроконтроллера. Или даже наноконтрольчика. |
Сообщ.
#195
,
|
|
|
А вообще так многие делают. Например, glib.
"ядро" - на plain-C без прикрас, а зато потом каждый сможет замутить биндинг под любой язык - и наслаждаться. |
Сообщ.
#196
,
|
|
|
Цитата Qraizer @ Нет, это граф-двиг для обычного писюка. Порт ни на какие древние компили не задумывался.Например, порт проекта на старый компиль. Добавлено 6 минут назад Или на недокомпиль для микроконтроллера. Или даже наноконтрольчика. Цитата Бобёр @ Если бы это была сяшечка или древний прожект я бы понял, но тут C++ и 2015-год. А вообще так многие делают. Например, glib. "ядро" - на plain-C без прикрас, а зато потом каждый сможет замутить биндинг под любой язык - и наслаждаться. |
Сообщ.
#197
,
|
|
|
Новый проект?
Ну, видимо, с авторами что-то не так |
Сообщ.
#198
,
|
|
|
Может им важна разрядность типов. Если будут портировать проект на платформу с не 32-разрядным int, меньше изменений делать.
|
Сообщ.
#199
,
|
|
|
Цитата D_KEY @ Я тоже так думаю.Ну, видимо, с авторами что-то не так Цитата Kray74 @ Я же написал - обычный писюк. А для точной разрядности давно уже введены соответствующие типы - http://www.cplusplus.com/reference/cstdint/ Может им важна разрядность типов. Если будут портировать проект на платформу с не 32-разрядным int, меньше изменений делать. |
Сообщ.
#200
,
|
|
|
Иногда хочется поиграться разрядностью помимо стандартных способов. Ну, в общем, эдакое поле для экспериментов в общем.
|
Сообщ.
#201
,
|
|
|
Цитата Бобёр @ А можно пример таких игр? Иногда хочется поиграться разрядностью помимо стандартных способов. Ну, в общем, эдакое поле для экспериментов в общем. |
Сообщ.
#202
,
|
|
|
Цитата Решение под спойлером, если вдруг кто захочет сам попробовать написать.Дана строка символов. Напишите цикл, за один проход удаляющий из неё все пробелы. Скрытый текст for (char *p = str; *p != '\0'; p += *p!=' ') *p = *(str += *str==' ')++; |
Сообщ.
#203
,
|
|
|
Цитата Qraizer @ Такие мысли:есть или нет в этом решении неопределённое поведение? 1.str может портиться (меняться), а вначале подумалось, что ввод 'p' избавит от этого. 2.К char* добавляется bool, что как бы не шибко красиво. |
Сообщ.
#204
,
|
|
|
Это всё не попадает под неопределённое поведение, Славян. А вот двойное изменение str во второй строке теоретически попадает. Однако у меня такое впечатление, что конкретно тут неопределённого поведения всё-таки нет.
|
Сообщ.
#205
,
|
|
|
В любом случае это говнокод. Да и ситуации, когда приходится разбирать, UB тут или нет, уже как правило не лучше UB.
|
Сообщ.
#206
,
|
|
|
Цитата Qraizer @ Согласен. Просто мысли такие были. Это всё не попадает под неопределённое поведение Цитата Qraizer @ Я тоже подумал, что кто-то реализует char в каком-нибудь контроллере как столько-то байтовый, а bool как столько-то. И понеслось... Но, в x86 ГОСТе, всё пока нормуль. А вот двойное изменение str во второй строке теоретически попадает. Однако у меня такое впечатление, что конкретно тут неопределённого поведения всё-таки нет. |
Сообщ.
#207
,
|
|
|
D_KEY, видишь ли... ты будешь смеяться, наверно... да и не только ты. Прикол в том, что это самое UB в выражениях у меня уже в рефлексах. Когда это написал, вообще не думал ни о чём. И вдруг спустя пару минут увидел двойное изменение str. Удивился, почему рефлекс не сработал. Смотрел внимательно, вроде всё на месте... но рефлекс теперь уже говорит, что тут нет UB.
Как-то так, в общем... |
Сообщ.
#208
,
|
|
|
Цитата Славян @ Я тоже подумал, что кто-то реализует char в каком-нибудь контроллере как столько-то байтовый, а bool как столько-то. И понеслось... Не понеслось. bool преобразуется к целочисленному типу (false=0, true=1) и складывается с указателем. Размеры char и bool не играют никакой роли. |
Сообщ.
#209
,
|
|
|
Цитата Kray74 @ true=1 Можно пруф? |
Сообщ.
#210
,
|
|
|
Тип bool вообще-то существует в двух ипостасях. Один - это обычно результат сравнения. Фактически это даже не данные, а точка перехода в программе. Такой bool при преобразовании однозначно переводится в числа 0 и 1. И такие же значения запоминаются в переменных. В Си результатами сравнений и логических операций были целые 0 и 1. В некоторых языках не так, и логические операции могут применяться к любым данным, давая результат соответствующего типа
Второй bool - это результат преобразования значения произвольного типа в логическое значение. Формально это результат выражения (v!=0), и компилятор должен привести результат к той же паре чисел. По крайней мере для сохранения читаемости программ следует заменять все ненулевые значения на 1. Так ли это в стандарте? |
Сообщ.
#211
,
|
|
|
Я-то думал, это известно любому студенту как минимум.
Цитата 4.12 Boolean conversions 1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false. Цитата 4.5 Integral promotions 6 A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one. |
Сообщ.
#212
,
|
|
|
Цитата Qraizer @ он это как-нибудь аргументирует? но рефлекс теперь уже говорит, что тут нет UB. |
Сообщ.
#213
,
|
|
|
Как бы да. Изменение str посредством += избыточно, т.к. не более чем помогает сэкономить одну итерацию. Основной фильтр пробелов осуществляется в += для p в заголовке цикла. Если предположить, что записи str перемешаются, то на пробеле всего лишь не сэкономится итерация. Однако не на пробеле цикл зациклится, и это будет явный фэйл.
Вот я и думаю, может ли тут компилятор перемешать записи в str. Что-то я запутался в статьях Стандарта. |