Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Motivation

Boost , ,

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Boost Exception

Motivation

Традиционно при использовании исключений для сообщения о сбоях сайт бросок:

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

Более высокий контекст в программе содержит уловку, которая:

  • выбирает неудачи на основе типов исключений;
  • проверяет объекты исключений на наличие данных, необходимых для решения проблемы.

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

Вот пример заявления об улове:

catch( file_read_error & e )
    {
    std::cerr << e.file_name();
    }

А вот возможный совпадающий бросок:

void
read_file( FILE * f )
    {
    ....
    size_t nr=fread(buf,1,count,f);
    if( ferror(f) )
        throw file_read_error(???);
    ....
    }

Очевидно, проблема в том, что обработчику требуется имя файла, но функция read_file не имеет имени файла, чтобы поместить его в объект исключения; все, что у него есть, это указатель FILE!

В попытке решить эту проблему мы можем изменить read_file, чтобы принять имя файла:

void
read_file( FILE * f, char const * name )
    {
    ....
    size_t nr=fread(buf,1,count,f);
    if( ferror(f) )
        throw file_read_error(name);
    ....
    }

Это не реальное решение: оно просто перекладывает бремя предоставления имени файла на непосредственного абонента функции read_file.

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

Exception wrapping

Идея обертывания исключений состоит в том, чтобы поймать исключение из функции более низкого уровня (например, функцию read_file выше) и бросить новый объект исключения, который содержит первоначальное исключение (и также несет имя файла). Этот метод, по-видимому, особенно популярен у программистов C++ с фоном Java.

Исключение обертывания приводит к следующим проблемам:

  • Чтобы обернуть объект исключения, его необходимо скопировать, что может привести к нарезке.
  • Обертывание практически невозможно использовать в общих контекстах.

Второй момент — это фактически особый случай нарушения принципа исключительного нейтралитета. Большинство контекстов в программе не могут обрабатывать исключения; такие контексты не должны мешать процессу обработки исключений.

The boost::exception solution

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

Например, в приведенном ниже заявлении о выбросе мы добавляем только код ошибки, поскольку это единственная информация, имеющая отношение к отказу, доступная в этом контексте:

struct exception_base: virtual std::exception, virtual boost::exception { };
struct io_error: virtual exception_base { };
struct file_read_error: virtual io_error { };
typedef boost::error_info<struct tag_errno_code,int> errno_code;
void
read_file( FILE * f )
    {
    ....
    size_t nr=fread(buf,1,count,f);
    if( ferror(f) )
        throw file_read_error() << errno_code(errno);
    ....
    }

В более высоком нейтральном контексте мы добавляем имя файла к исключению any, которое происходит от увеличения:: Исключение:

typedef boost::error_info<struct tag_file_name,std::string> file_name;
....
try
    {
    if( FILE * fp=fopen("foo.txt","rt") )
        {
        shared_ptr<FILE> f(fp,fclose);
        ....
        read_file(fp); //throws types deriving from boost::exception
        do_something();
        ....
        }
    else
        throw file_open_error() << errno_code(errno);
    }
catch( boost::exception & e )
    {
    e << file_name("foo.txt");
    throw;
    }

Наконец, вот как обработчик извлекает данные из исключений, которые вытекают из повышения:: исключение :

catch( io_error & e )
    {
    std::cerr << "I/O Error!\n";
    if( std::string const * fn=get_error_info<file_name>(e) )
        std::cerr << "File name: " << *fn << "\n";
    if( int const * c=get_error_info<errno_code>(e) )
        std::cerr << "OS says: " << strerror(*c) << "\n";
    }

Кроме того, boost::diagnostic_information можно использовать для составления автоматического (если не удобного для пользователя) сообщения, содержащего все объекты error_info, добавленные к boost:: Исключение. Это полезно для включения в журналы и другие диагностические объекты.

Статья Motivation раздела может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:29:14/0.0088241100311279/1