Информация об изменениях

Сообщение Re: Возврат ошибок из недр вложенных вызовов от 05.11.2020 23:06

Изменено 05.11.2020 23:14 bnk

Re: Возврат ошибок из недр вложенных вызовов
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Типичная ситуация: функция верхнего уровня вызывает функцию более низкого уровня, та — следующую и т.п., и где-то на N-м уровне очередной вызов возвращает ошибку. Если это что-то уникальное, то можно вернуть наверх (хоть через обычные return, хоть через исключения) уникальный код и/или описание. Но если ошибка общего характера (нехватка ресурсов, отказ в доступе, разрыв соединения и т.п.), то неплохо бы вернуть наверх более подробную информацию, которую можно показать пользователю, чтобы он имел более-менее адекватное представление о проблеме.


ЕМ>Например, в винде издавна принято возвращать отовсюду HRESULT. В результате, например, Windows Update при любой проблеме тупо выдает "failed" вместе с HRESULT, и даже по логам не сразу определишь, что и где обломалось. А программы на фреймворках типа .NET, наоборот, могут столь же тупо вывалить пользователю раскрутку стека, из которой он тоже мало что поймет, и которую таки лучше писать в лог. Хочется выдавать нечто промежуточное — не абстрактный "access denied", но и не историю вложенных вызовов в чистом виде.


ЕМ>Возникает соблазн завести какой-нибудь универсальный класс Result, и в процессе возврата изнутри наружу добавлять в объект уточнения, если необходимо. Но если возвращать его обычным образом, через return, то RVO/NRVO в отладочном режиме [практически] не используется, возвращаемые объекты (где будут минимум сотни байт) будут многократно копироваться, а функции нижнего уровня могут вызываться и сотни-тысячи раз в секунду. По той же причине не всегда годятся исключения — функции нижнего уровня не всегда возвращают ошибки, фатальные для верхних уровней.


ЕМ>Другой вариант — использовать TLS, как в винде для GetLastError. А как с этим в Linix/MacOS/Android/iOS?


ЕМ>Вообще, какие способы возврата уточненных результатов из многократно вложенных вызовов ныне считаются кошерными?


Если исключения слишком дороги, то вроде ничего кроме кода возврата не остается.
Как вариант видел много где, в том числе у Microsoft, паттерн "on error goto hell" для всякой низкоуровневой фигни, это код возврата с goto на очистку. пример

А так в нормальной практике это конечно исключения.
Вроде правила простые — если обработчик знает, что делать с ошибкой — обрабатывает, иначе пропускает наверх, возможно дописывая к нему какую-то полезную инфу (уточнение).
Re: Возврат ошибок из недр вложенных вызовов
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Типичная ситуация: функция верхнего уровня вызывает функцию более низкого уровня, та — следующую и т.п., и где-то на N-м уровне очередной вызов возвращает ошибку. Если это что-то уникальное, то можно вернуть наверх (хоть через обычные return, хоть через исключения) уникальный код и/или описание. Но если ошибка общего характера (нехватка ресурсов, отказ в доступе, разрыв соединения и т.п.), то неплохо бы вернуть наверх более подробную информацию, которую можно показать пользователю, чтобы он имел более-менее адекватное представление о проблеме.


ЕМ>Например, в винде издавна принято возвращать отовсюду HRESULT. В результате, например, Windows Update при любой проблеме тупо выдает "failed" вместе с HRESULT, и даже по логам не сразу определишь, что и где обломалось. А программы на фреймворках типа .NET, наоборот, могут столь же тупо вывалить пользователю раскрутку стека, из которой он тоже мало что поймет, и которую таки лучше писать в лог. Хочется выдавать нечто промежуточное — не абстрактный "access denied", но и не историю вложенных вызовов в чистом виде.


ЕМ>Возникает соблазн завести какой-нибудь универсальный класс Result, и в процессе возврата изнутри наружу добавлять в объект уточнения, если необходимо. Но если возвращать его обычным образом, через return, то RVO/NRVO в отладочном режиме [практически] не используется, возвращаемые объекты (где будут минимум сотни байт) будут многократно копироваться, а функции нижнего уровня могут вызываться и сотни-тысячи раз в секунду. По той же причине не всегда годятся исключения — функции нижнего уровня не всегда возвращают ошибки, фатальные для верхних уровней.


ЕМ>Другой вариант — использовать TLS, как в винде для GetLastError. А как с этим в Linix/MacOS/Android/iOS?


ЕМ>Вообще, какие способы возврата уточненных результатов из многократно вложенных вызовов ныне считаются кошерными?


Если исключения слишком дороги, то вроде ничего кроме кода возврата не остается.
Как вариант видел много где, в том числе у Microsoft, паттерн "on error goto hell" для всякой низкоуровневой фигни, это код возврата с goto на очистку. пример

А так в нормальной практике это конечно исключения.
Вроде правила простые — если обработчик знает, что делать с исключением — обрабатывает, иначе пропускает наверх, возможно дописывая к нему какую-то полезную инфу (уточнение).