Обновить
86
0
Евгений Охотников@eao197

Велосипедостроитель, программист-камикадзе

Отправить сообщение

На мой рабоче-крестьянский взгляд exception safety означает не отсутствие исключений, а отсутствие проблем при возникновении исключений. В данной статье показан конструктор копирования DynamicArray, который не обеспечивает никаких гарантий exception safety:

    DynamicArray(const DynamicArray& other)
        : data_(new T[other.capacity_]),
          size_(other.size_),
          capacity_(other.capacity_) {
// Кто будет освобождать память по указателю data_ если в одной
// из строчек ниже возникнет исключение?
        std::cout << "Copy constructor (copying " << size_ << " elements)\n";
        std::copy(other.data_, other.data_ + size_, data_);
    }

Любопытно, что С++ позволяет сделать перегрузку метода для случая const &&, что-то вроде:

struct demo {
  void f() const && { ... }
  ...
};

И вот если есть такая перегрузка, то std::move для константного объекта может иметь смысл.

Простая демонстрация: https://godbolt.org/z/MW8dMKvvK

Где это может пригодиться на практике лучше не спрашивать :)
Но с точки зрения возможности получить const && у std::move для константного объекта есть своя логика.

Да уж... Столько хорошей информации и правильных слов в самой статье, а потом хоба! И реализация DynamicArray в которой конструктор копирования не exception safe :(((

PS. Поскольку DynamicArray -- это всего лишь демонстрация, то придираться к тому, что он поддерживает только те T, которые являются DefaultConstructible, нет смысла.

Начиная с++11 шаблоны стали лечить, чтобы они были полезным инструментом

Пытаюсь оглянуться назад в 1995-й год, когда шаблоны начали появляться в доступных мне компиляторах... Да ведь они и тогда выглядели ну прям киллер-фичей, которой больше нигде не было. Из более-менее близкого к тогдашнему мейнстриму вспоминается разве что Ada со своим обобщенным программированием, но в Ada тогда еще не было ООП. А в C++ шаблоны были и для функций, и для классов, и даже для отдельных методов класса.

А уж сколько кода на шаблонах было написано до принятия С++11... Как-то сложно представить себе что все это было сделано на "неполезном" инструменте.

А вы хоть раз измеряли?

Да, когда исключения бросаются, то они могут дать просадку производительности на порядок, а то и на два. Кроме того, заранее неизвестно, сколько именно займет обработка исключения. Поэтому исключения под запретом в real-time. А это ведет к сегментированию в C++ (т.е. есть ниши где исключения под запретом, а есть где нет, и эти ниши сложно пересечь).

Я к тому, что если бы исключения были бы сделаны иначе (например, как в Eiffel) и были бы более дешевыми при использовании, такой проблемы с сегментированием в C++, возможно, не было бы.

Саттер несколько лет назад пытался продвинуть новый механизм для исключений. Но не взлетело до сих пор.

И часто она вам нужна, для не арифметических типов (или обертами над ними)?

Бывает. Но тут можно и другую аналогию привести: так ли часто парашютистам нужен запасной парашют? И если он нужен не часто, то есть ли смысл от него отказаться совсем.

Ну сделайте MyType::ToString и живите щастливо.

lavrov.jpg

При чем здесь MyType::ToString? Каким боком этот ваш "совет" поможет в DSL-естроении (например, вот таком)?

Оч странный у вас контраргумент. Да, в каких-то местах оно работает, в каких-то нет.

Т.е. вы пишите библиотеки, которые в каких-то местах работают, а в каких-то нет?

Контраргумент, которого вы, вероятно, не поняли, состоял в том, что если ваш код (например, ваша библиотека) использует чужой код, в котором исключения возможны (например, виде std::bad_alloc который может вылететь из push_back), то рассуждения о том, чтобы библиотека сама не бросала исключений становятся, скорее, росказнями, чем рассуждениями.

если ваш код не бросает исключений, то как бы...

Мой код, как правило, базируется на куче чужого кода.

Chromium собирается без поддержки исключений

Почему Google не использует у себя исключений уже многократно обсуждалось. А тем, кто не в курсе, можно попробовать прочитать соответствующий раздел из Google Code Style. С признанием того, что у исключений таки больше преимуществ. Только вот Google теперь дешевле продолжать писать без них.

Кроме того, далеко не у всех есть бюджеты Google. Если вы можете себе позволить писать больше менее надежного кода -- OK, можете извращаться как хотите, ваше право тратить свои деньги как вам вздумается.

Вы какой-то очень эмоциональный)

Вы еще и диагнозы через Интернет ставите?

Та в чем проблема-то?

Видимо, в попытке объяснить простые вещи.

Исключения, в сущности, ничем не лучше и не хуже кодов возвратов

Ну да, ну да.

ИМХО, главная проблема C++ных исключений в их высокой стоимости и последующей из нее непредсказуемости. Что поделать, исключения в C++ добавили тогда, когда большого опыта работы с исключениями еще ни у кого не было.

Ну, да, придется вместо MyType(...) писать MyType::Create(...). Велика ли потеря?

Да.

Следом за этим еще и перегрузка операторов идет в пешее эротическое.

В остальном тож самое)

Остается пожелать самому себе никогда не иметь дело с кодом, написанным такими экспертами.

Я бы даже сказал, есть много плюсов.

Говорите, говорите. Интернет, он все стерпит.

Если ничего не может внезапно сломаться в середине бизнес логики, потребителю библиотеки надо меньше думать.

facepalm.jpg

Если в середине бизнес-логики есть какой-нибудь условный vector::push_back, особенно если он скрыт под слоями абстракций, то ожидать, что ничего внезапно не сломается очень наивно. По меньшей мере.

Плюсом можно обмазаться в API слое всякими noexcept и получить какие-никакие плюсы к производительности)

Бездумное обмазывание noexcept -- прямой путь к внезапным падениям, а не к плюсам в производительности.

Просто пиши без исключений и...

Так можно и без C++ обойтись, но зачем?

Могу понять когда исключения под запретом где-то в системщине (когда драйвера для ОС на C++ пишут) или в hard-real time. Но вне этих ниш обмазываться std::expected-ами и отказывать себе в нормальных полноценных конструкторах... Видимо, вам в C++ слишком мало боли, хотите еще.

А вот делать библиотеки, которые могут информировать о проблемах как посредством исключений, так и без них... Ну на любителя занятие. Пробовали в прошлом, не понравилось. Желающие могут взглянуть как это может выглядеть в исходниках Asio, например. И это Asio, которое лишь тонкая обертка над системным API, в котором С++ных исключений нет (я про системный API).

А тут явно не моя "засада".

lavrov.jpg

Вот про эти "грабли" и приходится разъяснять всяким разным из "ясельных групп".

Разъяснять в стиле: "И для меня это осталось загадкой до сих пор."

Ну вперед.

Так было в какой-то момент, но вроде P2809 теперь определяет это как легитимный код.

Для многих практикующих C++ников стандарт C++26 еще не скоро станет обыденной реальностью.

В режиме Debug программа работала, т.е. ошибки нет и не было. Тут если и есть ошибка, то только не моя.

Детский сад, младшая ясельная группа. Когда приложение работает в Debug-е, но падает в Release, то с вероятностью в 99% -- это баг в программе, а не в компиляторе. Особенно в многопотоке, где время работы конкретных кусков кода критически важно при обращениях к разделяемым данным. В Debug-е код работает в разы медленнее и "времянка" (есть такой старый термин) распределяется совсем не так, как в Release. Из-за чего в Release проявляются такие фокусы, до которых не сразу и додумаешься.

Блин, это прописные истины, это грабли, по которым оттаптываются все, кто хоть мало-мальски имел дело с многопоточностью.

Компилятор не видит изменения для stop и считает, что выражение всегда истинно.

Так как автор хорошей библиотеки всегда должен держать в уме сценарий использования в среде с отключёнными исключениями.

Только вот это огромный геморрой (чтобы библиотека могла работать и так, и так). Поэтому нахер -- кому нужны условия без исключений, тот пусть ищет библиотеку без исключений или пишет такую библиотеку сам.

Т.е. ошибка ушла, словно и не было. И для меня это осталось загадкой до сих пор.

Т.е. вы совершили ошибку в многопоточном коде, найти ее не смогли, написали очередную графоманскую статью о том, как вы не можете в многопоточный код, но все равно позволяете себе иронизировать над "пот, боль и кровь"?

Тут проблема в том, что оптимизатор может "оптимизировать" этот код:
while (!stop) {}

ЕМНИП, в C++ (именно в С++, а не в чистом Си) бесконечный цикл без выраженных побочных эффектов -- это UB. И компилятор может сотворить все, что ему захочется.

И где там была "мина", ась? ;)

В ДНК

Т.е. когда все те волшебные пилюли, про которые вы тут рассказываете, не помогают вам же писать многопоточный код без багов, то вам остается только расставлять смайлики и неумно шутить про "заминировано"?

И тогда, возможно, не придется "мучиться с многопоточностью".

И как вы умудрились при такой-то любви и таких-то знаниях так вляпаться-то?

Я, надеюсь, не похож на «мазохиста», терпящего «пот, боль и кровь» многопоточности (см. обсуждение статьи [7]).

Во-первых, вы искажаете смысл исходной цитаты, а именно "голая многопоточность -- это пот, боль и кровь." Т.е. не многопоточность вообще, а многопоточность на базе самых низкоуровневых примитивов, от atomic-ов и на коленке склепанных самостоятельно lock-free структур до semaphores, mutexes, events и condition variables. К счастью, есть более высокоуровневые подходы, очень сильно (я бы даже сказал драматически) упрощающие многопоточное программирование (но это обходится далеко не бесплатно).

Во-вторых, есть другой термин для обозначения человека, рассуждающего о вещах, в которых он не разбирается.

параллельное программирование – это далеко не про скорость. Скорость – лишь ее побочный эффект.

А мужики-то и не знают...

Рассуждения о плохости неудачности дизайна std::filesystem выглядят пустопорожними, потому что нет примеров того, как это должно было бы выглядеть по мнению автора статьи.

1
23 ...

Информация

В рейтинге
4 746-й
Откуда
Гомель, Гомельская обл., Беларусь
Зарегистрирован
Активность