Pull to refresh

Comments 17

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

И тут вспоминаются пакеты типа OpenFOAM, которые при нехватке памяти падают с сегфолтом.

А что вы предлагаете сделать? Сохранение данных на каждом шаге по времени там и так можно включить (причём можно делать ротацию, чтобы не занимать диск)

По терминологии.
Термин «ответвенный код» в переводе «responsible code» там не употребляем (погуглите — даст «код» в значении правило). Например, фраза «использование strdub() — безответственно» у нас будет иметь смысл в силу культурологических особенностей. А там — нет. А как быть если целые проекты имеются на базе strdub? Вполне успешные, даже с утечками памяти.
Потому поднятый вами вопрос относится в области требований конкретного проекта, а не поведения программиста в целом. А писать в данном аспекте стоит о характеристиках типа fault-tolerance /отказоустойчивость или robustness /живучесть.

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

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


Но это в языках с исключениями, не знаю, как это поведение реализовать в Си. То, что вы предложили — возвращать код ошибки — тоже плохо и ненадежно, так как нет гарантий, что кто-то будет результат функции проверять. И ошибка просто останется незамеченной и выскочит на более позднем этапе, когда например при подготовке годового отчета выяснится, что в базе за год одни нули вместо данных. И теперь "компьютерщику" надо их как-то восстановить. В языках с исключениями такой проблемы нету.


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

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

exit() в библиотечном коде не даст почти ничего сделать вызывающему коду, не кинет исключение, не вернет ошибку, не вызовет деструкторы у переменных на стеке. Даже в лог ничего осмысленного записать не выйдет. Плюс если это мультитред, то судя по этому: www.cplusplus.com/reference/cstdlib/exit это может еще и к race condition привести
В лог — выйдет. В зрелой OS будет поддержка исключений типа линуксовых сигналов.
Не до конца понял что имеется ввиду. После exit из пользовательских функций вызовется только та, которая зарегистрирована в atexit. Там можно будет послать самому себе SIGTERM или еще что-нибудь, но зачем? Стэктрейс можно сохранить наверное, но обработчик из atexit будет вызван и при корректном завершении, следовательно надо как-то отделить вызов exit из библиотеки от остальных вариантов нормального завершения. Или я что-то не понял
Библиотечная функция наверняка пошлет сигнал. Что можно перехватить и записать в ЛОГ.
Ну это от библиотеки зависит уже, может и не кинуть. Если перехватить, ну да, можно coredump сделать и что-нибудь записать. Правда сигнал может не только от этой функции придти но и откуда-то еще извне, в итоге запись в логе получится не такая информативная, как хотелось бы
Не кинет — значит нарушит общие требования обработки нештатной ситуации. Дефект. Собственно об этом и статья — что делать в нештатных ситуациях.
> Не соглашусь. Именно так происходит в языках с исключениями, и это правильно.
Вы понимаете, что функция exit и исключения это совершенно разное?
То, что вы предложили — возвращать код ошибки — тоже плохо и ненадежно, так как нет гарантий, что кто-то будет результат функции проверять.

https://habr.com/ru/post/324642/ — это стандарт же


Аналогично нет никаких гарантий что исключение не проглотят.

Да, нет гарантии, что исключение при нехватке памяти как-то обработают и вообще хотят обрабатывать. Но важно другое. Что делать с проблемой — это решать программе! Когда библиотека позвала exit(), тут особенно уже не развернуться.

Ещё раз. Я не прошу и не требую, что каждая программа обязана обрабатывать ситуации нехватки памяти :). Хотя и считаю отсутствие обработки плохим тоном.

Я настаиваю на позиции, что что библиотека не имеет права решать за других, что нехватка программы == прекращение работы. Библиотека должна вернуть статус ошибки/сгенерировать исключение. А как уже поступить с этой информацией, решать приложению.
Я настаиваю на позиции, что что библиотека не имеет права решать за других
Золотые слова.

Есть разница между «не иметь возможности» и «не иметь желания» %)
Извиняюсь, я отвечал Sabubu выше и имел ввиду что главное — обработать ошибку. А возвращаемый это код/errno или исключение принципиального значения не имеет.
Полностью согласен с тем, что сама программа должна решать что делать с ошибкой. Задача библиотеки ошибку донести, а не убиться об неё.

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

Sign up to leave a comment.