2009-09-21 2 views
3

Какие методы я могу использовать для исключения исключений на C++, как указано в Google's style guide?Как я могу избежать использования исключений в C++?

+4

Не могли бы вы уточнить свой вопрос? Как бы то ни было, ответ будет выглядеть следующим образом: вы просто не бросаете исключения и стараетесь избегать ситуаций, которые вызывают внешний код для исключения исключений защитным кодированием. –

+0

Да, ваше понимание правильное. Что такое защитное кодирование? – yesraaj

+2

Обратите внимание, что даже с учетом того, что сказал sharptooth (http://stackoverflow.com/users/57428/sharptooth), и при всем уважении к умным людям в Google, я считаю это глупым руководством по стилю. Поскольку практически невозможно исключить исключения на C++, вам, вероятно, придется писать код, безопасный для исключения. Выполнение этого без использования исключений означает, что вам приходится иметь дело со всеми недостатками исключений, но отказаться от своих преимуществ. Теперь для чего это полезно? – sbi

ответ

8
  1. не бросать исключения.
  2. не следует использовать STL (что в значительной степени опирается на исключения).
  3. используйте только new(std::nothrow) или переопределить ::operator new для возврата 0 при ошибке.

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

+0

Я не понимал, что STL «сильно зависит от исключений», и я действительно помню, что STL, несовместимая с исключениями, была большой проблемой. Но я предполагаю, что это по крайней мере, поскольку у него нет другого способа справиться с неудачами распределения. –

+1

Это не просто вопрос сбоев распределения. Исключения - единственный способ указать отказ от конструкторов, особенно от конструкторов-копий, вызываемых элементами во время вставок. – avakar

+1

Проверьте EASTL, STL без исключений. –

1

В руководстве по стилю говорится, что они «не используют исключения», а именно: они не бросают их и не называет ничего, что могло бы их выбросить (например, они использовали бы new(std::nothrow) вместо обычного new потому что последний будет бросать bad_alloc, когда он не в состоянии выделить память.

+1

Как им удается использовать библиотеки, которые вызывают исключение? – yesraaj

+0

Или они не используют эту библиотеку –

+0

Они могут обернуть их и иметь и иметь улов (...) вокруг всего содержимого в каждой функции-обертки. – Laserallan

0

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

Кроме того, очевидно, первый шаг был бы избежать бросать исключения из вашего собственного кода, вероятно, с либеральным использованием nothrow directive, и попытаться избежать бросать исключения из внешнего (третьей стороны) кода через defensive programming.

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

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

3

Отбрасывание исключений в вашем собственном коде относительно просто: вы просто не используете оператор throw.

Не бросать исключения из ошибки выделения памяти является немного более болезненным: либо вы не используете нормальный new (используйте new(std::nothrow) или malloc или что-то вместо этого), или использовать какой-то нестандартный параметр компилятора, чтобы заставить его сделать что-то нестандартное, когда он не работает (например, немедленно завершите свою программу или верните 0), или вы переопределите operator new, чтобы сделать что-то нестандартное, когда оно не работает.

Если ваш выбранный подход заключается в немедленном прекращении программы, вы можете реализовать это с помощью set_new_handler(), о котором я забыл до тех пор, пока лампочка не напомнила мне.

Это не позволяет справиться с исключениями, генерируемыми библиотеками C++, которые вы не поддерживаете. Как правило, вам придется обернуть библиотечные вызовы в обертке, которая выглядит примерно так:

int DoSomething(int &output, const int input) throw() { 
    try { 
    output = library_do_something(input); 
    return 1; 
    } catch (...) { 
    return 0; 
    } 
} 

The catch (...) уловы все возможные C++ исключением из library_do_something (а также оператора присваивания на output, который не имеет отношения здесь), выбрасывает всю информацию, которую они могут содержать, а затем отображает все эти ошибки до 0.

Обратите внимание, что этот стиль означает, что вы вообще не можете использовать RAII, даже немного, потому что у вас нет возможности сообщить об ошибке в конструкторе. Весь смысл RAII в том, что вы приобретаете все свои ресурсы внутри конструкторов, чтобы они были должным образом выпущены деструктором во время распространения исключения. Но приобретение ресурсов - это то, что может по существу всегда терпеть неудачу. Поэтому вы не можете сделать это внутри конструктора.

+0

Вы можете установить новый обработчик. Оператор new будет вызывать его, когда он не имеет доступной памяти, и из этого обработчика вы можете либо получить память, либо завершить работу программы. –

+0

Я забыл про 'set_new_handler()', спасибо, litb! Я обновляю свой ответ. –

+0

Просто сделайте 'kill (0,9)' вместо того, чтобы выбрасывать исключение. Хорошо, вы также поцелуете всю свою группу процессов, но это отвратительное исключение не потревожит ваш красивый код! ;-) –

2

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

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

+0

Помимо проблем с производительностью и пространством исключений, которые эмпирически существуют, даже если люди отрицают их, некоторые платформы просто не поддерживают исключения в надежном порядке. Например, некоторые компиляторы встроенных компьютеров C++ просто не имеют рабочих исключений. – Crashworks

+2

Лично я не люблю использовать исключения в C++, потому что это чрезвычайно сложно предсказать поток управления программой. Поскольку любая функция C++ может вызывать любое исключение, не объявляя об этом, использование исключений означает, что вы не можете предсказать, какая функция * any * будет выполняться, если вы не превзошли все дерево вызовов «все» под ним. Это означает, что проверка поведения функций wrt exceptions является проблемой с геометрически увеличивающейся стоимостью для программиста. Java, OTOH, это правильно. Методы Java объявляют исключения, которые они могут использовать, и объявления выполняются во время компиляции. –

+0

@JeremyFriesner: Вот почему мы всегда кодируем гарантии безопасности исключений - так что не имеет значения, каков путь выполнения. – Tom

Смежные вопросы