Поделиться через


_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
*/

См. также

Распределение памяти
calloc
free
realloc