Рассмотрим пример фрагмента кода, который захватывает ресурсы и обращается к критической функции.
void critical ( char*, int );
int numread; char* buffer (NULL); // инициализация для детектирования возможных изменений int fd (-1); // ... аналогично try { buffer = new char[256]; fd = open ( "data", "r" ); // открываем файл и читаем по 256 символов while ( 0 < ( numread = read ( fd, buffer, 256 ) ) ) { critical ( buffer, numread ); // вызов критической функции } } catch ( ... ) { if ( 0 < fd ) close ( fd ); // освобождение ресурсов if ( buffer ) delete[] buffer; // ... аналогично throw; // делегирование исключения внешнему обработчику } if ( 0 < fd ) close ( fd ); // освобождение ресурсов if ( buffer ) delete[] buffer; // ... аналогично',
В этом примере видно, что операции по освобождению ресурсов повторяются два раза: при нормальном ходе выполнения и при возникновении критической ситуации. В некоторые языки программирования для такого случая была введена конструкция вида try-finally, в которой секция finally выполнялась обязательно, как при возникновении исключений, так и при нормальном ходе выполнения программы. Поскольку в языке C++ такой конструкции явно не присутствует, мы можем попытаться описать её самостоятельно, прибегая к помощи макропрепроцессора:
#define finally(Saver) \
catch ( ... ) \
{ \
Saver \
throw; \
} \
Saver
Тогда вышеприведенный код можно будет записать следующим образом:
char* buffer (NULL); int fd (-1), numread; try { buffer = new char [256]; fd = open ( "data", "r" ); // открываем файл и читаем по 256 символов while ( 0 < ( numread = read ( fd, buffer, 256 ) ) ) { critical ( buffer, numread ); // вызов критической функции } } finally ( // код освобождения ресурсов помещён в круглые скобки, так как if ( 0 < fd ) close ( fd ); // он является текстовым параметром макроса if ( buffer ) delete[] buffer; )
К недостаткам подобного решения, не позволяющим применять его в промышленных масштабах, следует отнести:
Более корректным с точки зрения языка способом является использование «стражей», специальных классов, которые следят за жизненным циклом объектов.