Существует ли общепринятая идиома для указания, что код C++ может выдать исключения?

. СЕТЕВАЯ компиляция в целом довольно легка: для получения ощущения этого самостоятельно просто захватите копию Отражатель.NET и дайте ему попытку.

В большинстве случаев, не будет никакой потребности перекомпилировать код для удаления простой проверки лицензий: просто исправляя MSIL добьется цели.

Защита себя против этого сценария приводит к быстро убывающей доходности: там будет всегда быть кем-то достаточно умным для обхода безотносительно дополнительных проверок, которые Вы добавляете к своему коду. Например, Вы могли добавить цифровую подпись к своему коду и отказаться к выполнению подписи, не соответствует (указание, что в код вмешались, например, для удаления проверки лицензий).

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

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

10
задан Duncan Jones 16 November 2018 в 08:36
поделиться

11 ответов

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

  • Гарантия отсутствия выброса: функция никогда не генерирует исключение
  • Сильная гарантия безопасности исключений: если генерируется исключение, объект будет оставлен в исходном состоянии.
  • Базовая гарантия безопасности исключений: если возникает исключение, объект остается в допустимом состоянии.

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

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

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

Что касается документации, когда вы ' способный точно определить, какие исключения может вызывать функция, во что бы то ни стало не стесняйтесь задокументировать это. Но в целом, когда ничего не указано, предполагается, что функция может вызывать. Спецификация пустого броска иногда используется для документирования, когда функция никогда не бросает. Если его там нет, предположим, что функция может выбросить.

7
ответ дан 3 December 2019 в 15:22
поделиться

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

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

Если вас интересует только MSVC, вы можете рассмотреть возможность использования пустой спецификации исключения или __ declspec (nothrow) для функций, которые не генерируют, и throw (...) для функций, которые выполняют. Это не приведет к неэффективному коду, потому что MSVC не генерирует код для проверки того, что функции, объявленные nothrow, на самом деле не бросают. GCC может сделать то же самое с -fno-enforce-eh-specs , проверьте документацию вашего компилятора. Тогда все будет автоматически задокументировано.

Вариант 2, try-catch для всего приложения на самом деле не «для безопасности», это просто потому, что вы думаете, что можете сделать что-то более полезное с исключением (например, распечатать что-то и выйти без ошибок), чем просто позволить C ++ вызов времени выполнения завершиться . Если вы пишете код, исходя из предположения, что что-то не сработает, а это действительно так, то вы могли остаться неопределенными до того, как одно из них действительно произойдет, например, если деструктор делает ложное предположение о согласованном состоянии.

Обычно я использую вариант (1): для каждого функционального документа, какие гарантии исключений он предлагает - без исключения, сильные, слабые или никакие. Последнее - это ошибка. Первое приветствуется, но редко, и при хорошем кодировании строго необходимо только для функций подкачки и деструкторов. Да, это может привести к ошибке пользователя, но любые средства кодирования C ++ с исключениями могут привести к ошибке пользователя. Затем, вдобавок к этому, также выполните (2) и / или (3), если это поможет вам обеспечить соблюдение (1).

Symbian имеет предстандартный диалект C ++ с механизмом под названием "leave", который похож на исключения в некоторых отношениях. В Symbian принято, что любая функция, которая может выйти, должна иметь название с буквой L в конце: CreateL , ConnectL и т. Д. В среднем это снижает количество ошибок пользователя, потому что вы можете видеть легче ли вы звоните то, что может уйти. Как и следовало ожидать, это ненавидят те же люди, которые ненавидят приложения в венгерской нотации, и если почти все функции оставить, она перестает быть полезной. И, как и следовало ожидать, если вы напишете функцию, у которой в имени отсутствует буква L, то в отладчике может пройти много времени, прежде чем вы обнаружите проблему, потому что ваши предположения уводят вас от фактической ошибки.

9
ответ дан 3 December 2019 в 15:22
поделиться

Честно говоря, почти любая функция C ++ может выбросить исключение. Вы не должны слишком беспокоиться о документировании этого, а вместо этого сделайте исключение кода безопасным, используя идиомы, такие как RAII.

6
ответ дан 3 December 2019 в 15:22
поделиться

Я использую и 1, и 2.

Примерно 1: Вы не можете избежать или предотвратить ошибку пользователя. Вы можете обыграть разработчика, который неправильно записал доксиген в кашу, если вы его знаете. Но вы не можете избежать или предотвратить ошибку пользователя, так что отбросьте паранойю. Если пользователь ошибся, то это сделал он, а не вы.

Примерно 2: В C # есть встроенный способ перехвата необработанных исключений. Так что это неплохая вещь, хотя, согласен, пахнет. Иногда лучше просто дать сбой, чем работать непоследовательно, но я практиковал регистрировать любые необработанные исключения и ТОГДА сбой. Это позволяет людям отправлять мне журнал, чтобы я мог проверить трассировку стека и отследить проблему. Таким образом, после каждого исправления происходит все меньше и меньше сбоев.

2
ответ дан 3 December 2019 в 15:22
поделиться

Документирование, кажется, единственный разумный метод, о котором я знаю.

Что касается спецификаций исключений, вот старая (2002 г.) статья Херба Саттера на эту тему http: // www.ddj.com/cpp/184401544 В нем обсуждается, почему эта особенность языка не обеспечивает безопасность во время компиляции, и в итоге делается вывод:

Итак, вот что кажется лучшим совет мы как сообщество узнали на сегодняшний день:

Мораль №1: Никогда не пишите исключение спецификации.

Мораль №2: Кроме, возможно, пустого один, но на вашем месте я бы избегал даже это.

2
ответ дан 3 December 2019 в 15:22
поделиться

C ++ до C ++ 11 определял спецификацию throw. См. этот вопрос . В прошлом по моему опыту компиляторы Microsoft игнорировали спецификацию C ++ throw. Само понятие «проверяемых исключений» является спорным, особенно в области Java. Многие разработчики считают это неудачным экспериментом.

2
ответ дан 3 December 2019 в 15:22
поделиться

Используйте документацию doxygen для описания ваших методов. Когда вы их используете,

1
ответ дан 3 December 2019 в 15:22
поделиться

Вы всегда должны ожидать исключений и обрабатывать их. К сожалению, есть

0
ответ дан 3 December 2019 в 15:22
поделиться


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

#include <stdexcept>

class MyException: public std::exception
{
    public:
    ~MyException() throw() {}
     char* what() const throw()
     {
        try
        {
            // Do Stuff that may throw
            return "HI";
        }
        // Exceptions must not escape this method
        // So catch everything.
        catch(...)
        {
           return "Bad Stuff HAppening Cant Make Exception Message.";
        }
     }
};
0
ответ дан 3 December 2019 в 15:22
поделиться

Существует способ указать, какие исключения функция может генерировать в C ++. Пример из книги Страуструпа

void f(int a) throw (x2, x3);

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

-1
ответ дан 3 December 2019 в 15:22
поделиться
  1. Укажите, какой уровень безопасности исключений гарантирует функция. Как указал Стив Джессоп в своем ответе, существует количество уровней. В идеале, если они задокументированы для всех интерфейсов или, по крайней мере, необходимый минимум: а) никогда не выбрасывает или б) может вызывать

    Прочтите о гарантиях безопасности исключений Abrahams , объясненных Херб Саттер .

  2. Я сильно сомневаюсь, что это будет практично в большой кодовой базе. Что касается далеко от выброса и , трудно понять, что делать. Проблемы , хорошее правило - ловить только в тех местах, где вы хотите иметь дело с исключениями, иначе пусть всплывет . Не рекомендуется перехватывать и гасить исключения, как только они появляются, просто потому, что ... они являются исключениями, поэтому вы чувствуете, что должны что-то с этим делать. В сложных системах хорошо иметь механизм регистрации, чтобы легче было отследить проблему.

  3. Не делай этого. Прочтите Прагматичный взгляд на спецификации исключений Херба Саттера и связанные статьи.

1
ответ дан 3 December 2019 в 15:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: