LINUX.ORG.RU

Исключения должны работать медленно?

 


1

3

Допустим у меня в контексте 100500 объектов. Внезапно возникает исключение и мы должны покинуть контекст. Начинают работать 100500 деструкторов. Некоторые работают очень медленно, например закрывают соединения с клиентов. Таким образом получается, что с момента возникновения исключения до начала его обработки в другом контексте могут проходить секунды. А мне это не надо. Как запретить выполнение деструкторов для определенных классов?


Ответ на: комментарий от RazrFalcon

Их уже можно пробрасывать без лапшы в стиле Go?

Я делал макрос CheckRet:

#define CheckRet(err) {status_t _err = (err); if (_err < B_OK) return _err;}

Потом можно писать так:

status_t Archive(BMessage *data, bool deep) const
{
	CheckRet(BView::Archive(data, deep));
	CheckRet(data->AddString("add_on", appSignature));
	CheckRet(data->AddColor("color", fColor));
	return B_OK;
}
X512 ★★★★★
()

Как запретить выполнение деструкторов для определенных классов?

Если не вдаваться в причины, по которым так надо сделать, то можно обернуть нужные нам классы в std::unqiue_ptr с переопределенным deleter, который либо пустой (что со стороны выглядит подозрительно), либо отправляет удаляемый объект в очередь на удаление в другой поток (объект уже не нужен, поэтому здесь нет необходимости сильно заморачиваться с его синхронизацией).

Marvel
()
Ответ на: комментарий от Dark_SavanT

Я где-то читала, люди попали в ситуацию, когда текла память в java программе. Они сделалали 2 (или 4) экземпляра программы, которые перегружали по очереди. И все работало.

Копроэкономика на марше.

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

Золотые слова.

dimgel ★★★★★
()
Ответ на: комментарий от Lzzz

ну теперь ты знаешь почему в с++ стараются не использовать исключения и почему джава тормозит. ещё можешь поизучать как сборщик мусора работает в додиезе, когда узнаешь, что сборщик мусора срабатывает когда окно сворачивается чтобы гуи не тормозило, ты переосмыслишь значение слова «хак».

anonymous
()
Ответ на: комментарий от RazrFalcon

Это был сарказм?

И да и нет. Ну, то есть, FTL реально существует, и там даже можно с std::optional работает емнип. Но рядовой писатель на C++ такое вряд ли поймёт, и проще сразу на хацкелле писать.

hateyoufeel ★★★★★
()

Как вариант, можно модифицировать деструкторы, чтобы они отправляли всю сложную обработку в отдельный пул потоков, не связанный с объектом.

Сам пул нужно спроектировать должным образом. Готовых решений для С++ я не встречал.

trex6 ★★★★★
()
Ответ на: комментарий от anonymous

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

если обработчика исключения нет - сразу terminate и досвидос. ну а смысл разворачивать стек если это всё равно закончится завершением приложения?

anonymous
()

Доктор, мне больно, когда я делаю медленные деструкторы.

rupert ★★★★★
()
Ответ на: комментарий от fsb4000

Или какие-нибудь библиотеки использовать для этого.

Какие? Все что я видел, используют расширения компилятора.

RazrFalcon ★★★★★
()

1. Сделать класс особого исключения.

2. В случаях когда вам нужно принудительно избежать «раскрутку» 100500 объектов вызывать кидать именно объект данного класса исключения.

3. В этом специальном классе исключении вызвать принудительное завершение процесса. Не помню уже подробности но когда-то я делал подобный класс исключения, он имел реализацию под winApi и posix, и для каждой из них вызывал нативную ф-ии завершения процесса или потока, не помню увы детали. Возможно хватит и вызова exit https://stackoverflow.com/questions/7054685/are-destructors-run-when-calling-....

Вообще исключения довольно быстро работающая штука, если написаны как легкие классы, без работы с динамикой. Более того можно через макросы и шаблоны сделать очень классные классы исключений, которые смогут в себя аккумулировать достаточно много информации - текстовое описание, место возникновения (файл, класс, сторока) - и все это будет работать быстро. Но придётся правда обоснавать перед любителями «не платить за то что не используем» создание статического буфера для хранения данных для исключения которрое возмозно создастся а возможно нет :)

bonta ★★★★★
()
Последнее исправление: bonta (всего исправлений: 1)
Ответ на: комментарий от anonymous

Не верно. Правильнее сказать в некоторых областях применения Си++ стараются не использовать исключения. В большинстве же проектов на Си++ - их активно используют. Т.к. это в разы удобнее и делает код чище и проще, чем работа с кодами возврата.

bonta ★★★★★
()
Ответ на: комментарий от Lzzz

Шоп у тебя деньги на карте при покупке захолдировали и забили на возврат при исключительной ситуации под соусом «а фиг с ним через несколько дней без подтверждения трансакции деньги банк сам расхолдирует»

cobold ★★★★★
()
Ответ на: комментарий от RazrFalcon

Такой макрос не умеет пробрасывать ошибки разных типов.

Можно status_t заменить на std::optional, _err < B_OK на _err.has_value() и использовать ссылки или что больше нравится.

X512 ★★★★★
()
Последнее исправление: X512 (всего исправлений: 1)
Ответ на: комментарий от Lzzz

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

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

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

anonymous
()
Ответ на: комментарий от bonta

заворачивание кодов возврата в понятие объекта код чище не делает, если такое имеет место быть это лишь особенности реализации, в данном случае плохой на кодах возврата и хорошей на исключениях.

anonymous
()
Ответ на: комментарий от bonta

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

anonymous
()

Don't abuse exceptions and be happy. Or use exceptions only in exceptional cases and be happy.

/thread

anonymous
()
Ответ на: комментарий от RazrFalcon

по ответам в теме можно подумать что Lzzz это другой ник RazrFalcon

который не хочет ударять лицом в грязь

вот и набрасывает от другого ника

anonymous
()

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

anonymous
()
Ответ на: комментарий от anonymous

facepalm еще один мамкин специалист

ну давайте предположим то там не исключения а коды возврата

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

anonymous
()
Ответ на: комментарий от anonymous

При любом раскладе выполнить несколько проверок будет быстрее, чем будет генерироваться и выбрасываться исключение.

anonymous
()
Ответ на: комментарий от anonymous

заберите этих мамкиных какеров с моего лорчика

facepalm facepalm еще сто лет назад уже все разжевали что исключения - зерокост

и все время уйдет не на генерацию исключения

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

anonymous
()

Исключение - повод для завершения программы. Скорость обхода деструкторов тут уже не важна.

anonymous
()
Ответ на: комментарий от Lzzz

нужно дождаться запрос от клиента (когда он придет никто не знает) и вернуть ему код ошибки.

Не нужно. Перебьется клиент.

anonymous
()
Ответ на: комментарий от anonymous

Исключение - повод для завершения программы.

Исключение - это еще один способ выйти из подпрограммы/процедуры/функции (как будто не хватает стандартных способов выхода процедурного программирования и ООП).

Плохо, что при выходе приходится входить в другие подпрограммы, где тоже может возникнуть исключение, и придётся выходить из выхода :)

anonymous
()
Ответ на: комментарий от anonymous

Зачем нервничать? Никогда исключения в цепепе не были зерокост. Хотя бы по причине того, что для них требуется аллокация на хипе. Facepalm.

anonymous
()
Ответ на: комментарий от Lzzz

да, raii то, что нужно. и тут нужно понимать, что raii - это объект бизнес логики. при выходе из функции (не важно почему, исключение, return, просто конец…) будет вызван деструктор и этим нужно воспользоватся, а не боротся. язык это просто инструмент, его надо использовать, а не ругатся, что языковой механизм исправно работает.

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

например есть объект соединения. при его разрушении оно закроектся. при исключении надо просто упасть (std::terminate например). ок, можно использовать raii у которого есть метод close, если он не был вызван то в деструкторе падаем. close например ресетит std::optional (не будет алоцирована память в куче). (ну тут я не очень поинмаю зачем тогда закрывать соединение при нормальной работе? если это просто утилита, которая отработает и все, может можно просто не убирать за собой?)

имхо объект, который в конструкторе открывает а в деструкторе закрывает соединение, типа пока есть объект есть и соединение, не очень подходит именно под соединение. его может закрыть другая сторна, поэтому все равно придется вводить состояние «невалидное соединение». можно ввести аналогию с detach и join..

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.