Программирование в среде Windows, обработка исключительных ситуаций, страница 5

    delete floatarray;

    return buffer;

}

Когда в функции АllocateBuffer() выбрасывается исключение, остальные операторы теле функции не выполняются. По этой причине динамически созданный массив floatarray не будет удален. Объект BigObject, размещенный в стеке, выйдет из области видимости будет автоматически вызван его деструктор, удаляющий переменную-член intarray, созданную в конструкторе объекта с помощью оператора new. Эту важную концепцию следует глубоко усвоить: объекты, размещенные в стеке, будут удалены с помощью их деструкторов в процессе освобождения стека. С объектами, память под которые была выделена из кучи, этого не произойдет — об их удалении должна позаботиться созданная вами программа. К примеру, функция AllocateBuffer() должна содержать операторы, удаляющие массив floatarray, до оператора вызова исключения, как показано ниже:

if (buffer == NULL)

{

MyException* exception = new MyException ("Memory allocation failed! ");

delete floatarray;

throw exception;

}

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

int* Intermediate()

{

    BigObject bigarray;

    float* floatarray = new float[1000];

    int* retval = NULL;

    try

    {

    retval = AllocateBuffer();

    }

    catch (MyException e)

    {

      delete floatarray;

    throw;

    }

    delete floatarray;

    return retval;

}

Пересмотренная версия функции Intermediate() перехватывает исключение, что дает возможность удалить выделенную под floatarray память, а затем повторно выбрасывает исключение, передавая его на обработку в вызывающую функцию. (Обратите внимание, что в новом операторе throw отсутствует параметр— повторно выбросить можно только то исключение, которое было перед этим перехвачено.) Ниже приведено несколько замечаний, касающихся этой пересмотренной функции.