Парадигмы обработки ошибок: смешивание исключений и кодов ошибок - PullRequest
1 голос
/ 18 апреля 2011

В настоящее время я занимаюсь разработкой игрового движка на C ++ с использованием различных компонентов промежуточного программного обеспечения, включая OGRE (графика), Bullet (физика) и OpenAL (звук), и я довольно рано в проекте.Именно в этот момент я настраиваю свои механизмы обработки ошибок.

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

Я склонен использовать коды ошибок в качестве моихмеханизм сообщений об ошибках вместо исключений, так как

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

Единственная проблема, которая возникает тогда, связана с конструкторами - они не могут возвращать коды ошибок.Поэтому я планирую использовать коды ошибок для всех методов, но выбрасывать исключения, когда конструкторы терпят неудачу.Так как я планирую использовать шаблон фабричного метода для генерации объектов и передачи их в пользовательский код, исключения будут обрабатываться внутренним механизмом, и пользователь просто получит нулевой указатель на сбой конструкции.Я понимаю, что вы обычно не должны смешивать исключения и коды возврата, но альтернативы звучат не лучше:

  • Вы не можете ничего сделать в конструкторе и использовать какой-то метод init (), но там идет RAII.
  • Вы можете установить флаг и иметь какой-то метод isOk () или isInitialized (), но теперь вы ввели возможность некоторого состояния зомби, где объект существует, но не смогинициализировать, и вы можете забыть проверить, чтобы убедиться, что он жив.

Я знаю о затратах и ​​преимуществах обеих систем, и понимаю, что смешивать их, как правило, плохая идея.Однако, поскольку конструкторы не могут иметь какое-либо возвращаемое значение, было бы неразумным генерировать исключения, когда конструкторы терпят неудачу и используют коды ошибок в другом месте?У кого-нибудь есть лучшее предложение?

Ответы [ 3 ]

1 голос
/ 19 апреля 2011

Я лично предпочитаю исключения (и для этого есть много веских причин).Но, конечно, выбрасывать исключения из кода DLL в код пользователя (и наоборот) - плохая идея.Поэтому в вашей ситуации я использовал бы исключения внутри модулей (как DLL, так и исполняемых) и использовал бы API на основе error_return для экспорта DLL.При использовании API DLL на основе error_return, я бы использовал обертки на основе исключений для этих функций error_return-ing.

IMO возвращает индикаторы ошибок любым способом (по возвращаемому значению или через ссылку или через коды ошибок для каждого потока)путает код с бесконечными ветвями проверки ошибок.Мой путь (и мое понимание пути C ++) возвращается только в случае успеха.

0 голосов
/ 18 апреля 2011

Я предпочитаю сейчас работать только с исключениями, но если вам все еще нужно или вы хотите использовать коды ошибок с конструкторами, мне нравится подход, который заставляет пользователя передавать параметр в конструкторе:

class Foo {
    public:
        Foo(int &errorCode) {
            //our init code
            rc = SOMETHING_BAD;
        }
};

//on a method or function:
int errorCode;
Foo foo(errorCode);
if(errorCode != RESULT_OK)
{
      //handle it
}

Я думаю, что это лучше, чем использование метода IsOk () или отдельного метода Init, потому что он по крайней мере вынуждает пользователя передавать переменную в качестве параметра и трудно забыть проверять ошибки, недостатком является то, что иногда это скучнообъявлять переменные только для этого.

Мои 2 цента.

0 голосов
/ 18 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...