Страницы

Поиск по вопросам

пятница, 19 октября 2018 г.

Лучший способ сказать о ошибке в Си

Пишу небольшую библиотеку, с функциями, которыми кто-то будет пользоваться. В функциях случаются ошибки, о которых нужно каким-то образом сообщить. Казалось бы — банальная вещь, но везде сделано по-разному. Мне интересны преимущества каждого способа, их для меня пока три:
Возвращать true или false. Пользователь библиотеки сам будет проверять возвращаемое значение и в зависимости от него выводить сообщение об ошибке. Самостоятельно в функциях библиотеки сообщать в подробностях о всех предупреждениях или ошибках, exit'ом убивать приложение, ничего не возвращая. Возвращать true или false, но при этом ещё и записывать ошибку в специальный буфер. Пользователь библиотеки может узнать об ошибке, вызвав функцию GetError(). Так сделано в SDL
По-моему, лучше всего использовать второй способ, но зачем тогда SDL усложняет всё своими GetError/SetError? Зачем тот же EGL возвращает только код ошибки? Прошу сказать о плюсах/минусах того или иного способа, они ведь наверняка есть.


Ответ

При написании библиотечного кода надо иметь в виду, что пользоваться этим кодом могут совершенно разные приложения. Поэтому вывод куда-либо явного сообщения об ошибке может просто не сработать, т.к. этого "куда-либо" может вовсе не существовать в текущем окружении (об этом уже упомянул @AntonShchyrov в своем ответе). Более того, язык сообщения может быть вовсе не подходящим для пользователя.
Наиболее подходящим вариантом будет предоставить дополнительную функцию или переменную, откуда можно получить код/текст последней ошибки. Существующие варианты такого подхода это errno, GetLastError и т.п. В этом случае, пользователь библиотеки может сам решить куда ему следует (и следует ли вообще) выводить сообщение об ошибке.
Отсюда же вытекает и решение о недопустимости вызова exit из библиотечного кода. По крайней мере, если нет соответствующей функции в библиотеке, которая меняет это поведение (по умолчанию никаких активных exit быть не должно). Пользователю может быть вообще хочется наплевать на обработку ошибок и просто работать дальше, а библиотека рушит ему всё приложение из N потоков на корню.
Возвращать из каждой функции признак успешности её выполнения через return может быть не совсем удобно, т.к. в первую очередь функция должна возвращать то, на что она заточена, а не признак ошибки или код возврата. Для примера, представьте, как будет выглядеть функция типа strlen в таком случае и насколько удобно будет ей пользоваться при этом.
В любом случае, способы оповещения пользователя библиотеки об ошибочных ситуациях должны быть чётко прописаны в руководстве.

Комментариев нет:

Отправить комментарий