_set_new_handler
Передает управление механизму обработки ошибок, если оператору new
не удается выделить память. Компилятор Microsoft C++ использует эту функцию для реализации std::set_new_handler
в стандартной библиотеке.
Синтаксис
_PNH _set_new_handler( _PNH pNewHandler );
Параметры
pNewHandler
Указатель на предоставленную приложением функцию обработки памяти. Аргумент 0 или nullptr
вызывает удаление нового обработчика.
Возвращаемое значение
Возвращает указатель на предыдущую функцию обработки исключений, зарегистрированную функцией _set_new_handler
, чтобы предыдущую функцию можно было впоследствии восстановить. Если предыдущая функция не задана, возвращаемое значение можно использовать для восстановления поведения по умолчанию. Это значение может быть nullptr
или 0.
Замечания
Функция C++ _set_new_handler
определяет функцию обработки исключений, которая получает управление, если оператор new
не смог выделить память. Если оператор new
завершается ошибкой, система времени выполнения автоматически вызывает функцию обработки исключений, которая была передана в качестве аргумента в функцию _set_new_handler
. _PNH
, определенный в <new.h>
, является указателем на функцию, которая возвращает тип int
и принимает аргумент типа size_t
. Используйте size_t
для определения объема выделяемого пространства.
Обработчик по умолчанию отсутствует.
_set_new_handler
фактически является схемой сборки мусора. Система времени выполнения делает попытку выделения памяти каждый раз, когда пользовательская функция возвращает ненулевое значение, и завершается неудачей, если пользовательская функция возвращает 0.
Вхождение функции _set_new_handler
в программе регистрирует в системе времени выполнения функцию обработчика исключения, указанную в списке аргументов:
// _set_new_handler1.cpp
#include <new.h>
int handle_program_memory_depletion( size_t )
{
// Your code
}
int main( void )
{
_set_new_handler( handle_program_memory_depletion );
int *pi = new int[BIG_NUMBER];
}
По умолчанию _set_new_handler
глобальное состояние функции распространяется на приложение. Чтобы изменить его, ознакомьтесь с глобальным состоянием в CRT.
Можно сохранить адрес функции, которая была передан последней в функцию _set_new_handler
, и восстановить ее позже:
_PNH old_handler = _set_new_handler( my_handler );
// Code that requires my_handler
// . . .
_set_new_handler( old_handler )
// Code that requires old_handler
// . . .
Функция C++ _set_new_mode
задает новый режим обработчика для malloc
. Новый режим обработки указывает, должна ли функция malloc
при сбое вызывать новую подпрограмму обработчика, заданную функцией _set_new_handler
. По умолчанию malloc
не вызывает новую подпрограмму обработчика при сбое выделения памяти. Можно переопределить это поведение по умолчанию, чтобы в случае сбоя предоставления памяти функцией malloc
функция malloc
вызывала новую подпрограмму обработчика таким же образом, как это делает оператор new
при сбое по той же причине. Чтобы переопределить значение по умолчанию, вызовите _set_new_mode(1);
в начале программы или свяжите с newmode.obj
ним.
Если пользователь определен operator new
, новые функции обработчика не вызываются автоматически при сбое.
Дополнительные сведения смnew
. в delete
справочнике по языку C++.
Существует один _set_new_handler
обработчик для всех динамически связанных БИБЛИОТЕК DLL или исполняемых файлов в одном процессе. Даже при вызове _set_new_handler
обработчик может быть заменен другим. Кроме того, новый обработчик может заменить обработчик, заданный другой библиотекой DLL или исполняемым файлом в процессе.
Требования
Function | Обязательный заголовок |
---|---|
_set_new_handler |
<new.h> |
Дополнительные сведения о совместимости см. в разделе Совместимость.
Пример
В этом примере при сбое выделения элемент управления передается MyNewHandler
в . Переданный аргумент MyNewHandler
— это число запрошенных байтов. Возвращаемое значением MyNewHandler
является флаг, указывающий, следует ли извлекать выделение: ненулевое значение указывает, что выделение должно быть извлечено, а нулевое значение указывает, что выделение завершилось сбоем.
// crt_set_new_handler.cpp
// Build for x86.
// WARNING: This code intentionally allocates memory until an allocation fails.
// Running this code can cause your system to become non-responsive.
#include <iostream>
#include <new>
#include <new.h>
static const int Big_number = 0x03FFFFFF;
struct MemoryHog {
int pork[Big_number];
};
class MemoryReserve {
MemoryHog* reserved = nullptr;
public:
MemoryReserve() {
reserved = new MemoryHog();
}
~MemoryReserve() noexcept {
if (reserved != nullptr)
delete reserved;
}
bool free_reserve() noexcept {
if (reserved != nullptr) {
delete reserved;
reserved = nullptr;
return true; // return true if memory freed
}
return false; // reserved memory exhausted.
}
};
// Global singleton for a MemoryReserve object
static MemoryReserve reserve{};
// Define a function to be called if new fails to allocate memory.
int MyNewHandler(size_t /* unused */)
{
// Call a function to recover some heap space. Return 1 on success.
if (reserve.free_reserve()) {
std::cerr << "MyNewHandler: Released reserved memory.\n";
return 1;
}
std::cerr << "MyNewHandler: Reserved memory exhausted.\n";
return 0;
}
static const int max_depth = 16; // recursion depth limiter
static int depth = 0;
void RecurseAlloc() {
MemoryHog* piggy = new MemoryHog{};
if (++depth < max_depth) // Recurse until memory exhausted or max_depth
RecurseAlloc();
depth--;
delete piggy;
return;
}
int main()
{
try {
_set_new_handler(MyNewHandler); // Set handler for new.
RecurseAlloc();
}
catch (std::bad_alloc& ex) {
std::cerr << "bad_alloc caught: " << ex.what() << '\n';
}
}
/* Output:
MyNewHandler: Released reserved memory.
MyNewHandler: Reserved memory exhausted.
bad_alloc caught: bad allocation
*/