Существует дополнительное средство, которое можно применить для
реализации обработки отказов new. Функция set_new_handler (с прототипом в
заголовочном файле <new>) принимает в качестве аргумента указатель на
функцию, которая не принимает аргументов и возвращает void. Этот указатель
регистрируется как функция, которая должна вызываться при отказах new. Тем
самым программисту предоставляется стандартный метод обработки всех
отказов new вне зависимости от того, в каком месте программы возникла
ошибка. После того как обработчик new зарегистрирован в программе вызовом
set_new_handler, операция new при отказах не будет выбрасывать
исключений bad_alloc; вместо этого она будет пересылать ошибку
зарегистрированному обработчику.
Если new удалось выделить память, она возвращает указатель на нее. Если
память выделить не удается и никакой функции обработчика new с помощью
set__new_handler зарегистрировано не было, операция new выбрасывает
исключение bad_alloc. Если память выделить не удается и была
зарегистрирована функция обработчика new, то вызывается эта функция. Стандарт C++
|
|
определяет, что функция обработчика new должна выполнить одно из следующих
действий:
1. Увеличить объем доступной памяти путем освобождения других областей
динамической памяти (либо попросить пользователя закрыть другие
приложения) и возвратиться к операции new, чтобы возобновить
попытки выделения памяти.
2. Выбросить исключение типа bad_alloc.
3. Вызвать функцию abort или exit (обе из заголовочного файла <cstdlib>)
для завершения программы.
Программа на рис. 16.7 демонстрирует set_new_handler. Функция
customNewHandler (строки 14-18) печатает сообщение об ошибке (строка 16),
а затем завершает программу вызовом abort (строка 17). Вывод показывает,
что программа выполнила всего две итерации цикла, после чего new потерпела
неудачу и активировала функцию customNewHandler. У вас вывод
программы может отличаться от нашего в зависимости от объема физической памяти,
дискового пространства, доступного для виртуальной памяти на вашей
системе, и используемого компилятора.
// Рис. 16.7: test7.cpp
// Демонстрация set_new__handler.
#include <iostream>
using std::cerr;
using std::cout;
#include <new> // стандартная операция new и set__new_handler
using std::set_new_handler;
#include <cstdlib> // прототип функции abort
using std::abort;
using std::endl;
// обработать неудачу выделения памяти
void customNewHandler()
{
cerr << "customNewHandler was called" << endl;
std::abort();
} // конец функции customNewHandler
// применение set_new__handler для обработки исключения new
int main()
{
double *ptr[ 50 ];
// указать, что при неудачном выделении памяти
// должна вызываться функция customNewHandler
set_new_handler (customNewHandler);
// выделить память для ptr[ i ]; при неудаче выделения памяти
// будет вызвана функция customNewHandler
for (int i = 0; i < 50; i++)
{
ptr[ i ] = new double[ 50000000 ]; // возможно исключение
cout << "Allocated 50000000 doubles in ptr[ " << i << " ]\n";
} // конец for
return 0;
} // конец main
/*
Allocated 50000000 doubles in ptr[ 0 ]
Allocated 50000000 doubles in ptr[ 1 ]
customNewHandler was called
Abnormal program termination
*/