LINUX.ORG.RU

Неопределенное поведение как стратегия обработки ошибок

 ,


0

1

Тред по мотивам std::string length возвращает 16777215. Если для Ъ там после операции pop_back для пустой строки возвращалось в вызове length все, что угодно. Соответственно, вопрос: допустимо ли такое вообще? Исключения можно отловить, коды ошибок - обработать, а тут что? Надеяться на статический анализатор? Обкладывать каждую строку кода тестами на не знаю что? Поминутно открывать талмуды стандарта и искать описание похожего примера? Когда вызов библиотечной, даже не встроенной функции, стал привязываться к стандарту языка и им оправдываться? И когда разработчики научатся обрабатывать граничные ситуации так, чтобы написанный ими код не сходил с ума у клиентов?

Ваши мнения по поводу практики при обработке ошибок ссылаться на неопределенное поведение.

Моё мнение - должны быть как safe так и unsafe операции, причём unsafe операции должны прям иметь этот суффикс в своём имени. Что-то вроде pop_unsafe(). Соответственно первая операция должна вставлять уместные проверки, вторая быть максимально быстрой. При разработке программист должен использовать первый вариант. Потом на этапе тестирования и отладки, если выясняется, что замена этот функции даст необходимое ускорение - то заменить на unsafe, причём даже unsafe должна требовать специального флага для отключения проверок, аналога NDEBUG.

А в 99.99% случаев дополнительные проверки не вносят существенного замедления, но вносят существенное уменьшение багов.

vbr ★★★
()

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

Чего??? Какие такие «встроенные» функции? Куда они встроенные? В компилятор? Это если интринзики, то да, но поп_бэк - это не интринзик. И да, может быть для кого-то это сюрприз, но STL - часть стандарта C++.

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

А тут надо читать справку, прежде чем использовать неизвестные тебе вещи. Сказано «Calling pop_back on an empty container results in undefined behavior» - значит идешь, и проверяешь сначала размер контейнера. Дофига всяких мест, где нужно делать сначала проверки, прежде чем писать куда попало. Например, результат std::find может быть std::end, и это надо проверять, прежде чем долбиться по адресу.

Поминутно открывать талмуды стандарта

какие в попу талмуды стандарта?! Справка, en.cppreference.com.

seiken ★★★★★
()
Последнее исправление: seiken (всего исправлений: 1)

жизнь несовершенна. если ты будешь проверять внутри pop_back валидность этой операции, то ты будешь терять в производительности. если не будешь - есть возможность UB.

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

alysnix ★★★
()

_GLIBCXX_DEBUG объявлять не пробовал?

$ cat empty_str.cpp 
#include <string>

int main()
{
    std::string().pop_back();
}

$ g++ -D_DEBUG -D_GLIBCXX_DEBUG -Og empty_str.cpp -o empty_str

$ ./empty_str                                                 
/usr/include/c++/13/bits/basic_string.h:2119: void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::pop_back() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]: Assertion '!empty()' failed.
[1]    11679 IOT instruction (core dumped)  ./empty_str

rupert ★★★★★
()

Соответственно, вопрос: допустимо ли такое вообще?

В стандарте же написано.

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

Как только кончились ещё более смутные достандартные времена.

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

Не делать так™.

t184256 ★★★★★
()
Последнее исправление: t184256 (всего исправлений: 1)

Дык вроде в прошлом треде разобрались: кому нужны проверки, тот их включает ручками пролистав документацию на свою STL до нужного раздела. И это прекрасно согласуется с идеей C++ - не платишь за то, что не используешь. В конце концов для C таких требований никому в голову предъявлять не приходит, а C++ создавался чтобы занять немалую часть его нишы.

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

dvetutnev
()