_set_new_handler

Transfere o controle ao mecanismo de gerenciamento de erros se o operador new não conseguir alocar memória. O compilador Microsoft C++ usa essa função para implementar std::set_new_handler na biblioteca padrão.

Sintaxe

_PNH _set_new_handler( _PNH pNewHandler );

Parâmetros

pNewHandler
Ponteiro para a função de manipulação de memória fornecida pelo aplicativo. Um argumento de 0 ou nullptr faz com que o novo manipulador seja removido.

Retornar valor

Retorna um ponteiro para a função de manipulação de exceção anterior registrada por _set_new_handler, de modo que a função anterior possa ser restaurada posteriormente. Se nenhuma função anterior tiver sido definida, o valor retornado poderá ser usado para restaurar o comportamento padrão. Esse valor pode ser nullptr ou 0.

Comentários

A função _set_new_handler C++ é usada para especificar uma função de manipulação de exceção que assumirá o controle se o operador new falhar ao alocar memória. Se new falhar, o sistema de tempo de execução chamará automaticamente a função de manipulação de exceção que foi passada como um argumento para _set_new_handler. _PNH, definido em <new.h>, é um ponteiro para uma função que retorna o tipo int e leva um argumento do tipo size_t. Use size_t para especificar a quantidade de espaço a ser alocado.

Não há manipulador padrão.

_set_new_handler é essencialmente um esquema de coleta de lixo. O sistema de tempo de execução repete a alocação cada vez que a função retorna um valor diferente de zero e falha se a função retorna 0.

Uma ocorrência da função _set_new_handler em um programa registra a função de manipulação de exceção especificada na lista de argumentos com o sistema de tempo de execução:

// _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];
}

Por padrão, o estado global da função _set_new_handler tem como escopo o aplicativo. Para alterar isso, confira Estado global no CRT.

Você pode salvar o último endereço de função a ser passado para a função _set_new_handler e restabelecê-lo mais tarde:

   _PNH old_handler = _set_new_handler( my_handler );
   // Code that requires my_handler
   // . . .
   _set_new_handler( old_handler )
   // Code that requires old_handler
   // . . .

A função _set_new_mode C++ define o novo modo do manipulador para malloc. O novo modo do manipulador indica se, em caso de falha, malloc deverá chamar a nova rotina do manipulador, conforme definido por _set_new_handler. Por padrão, malloc não chama a nova rotina do manipulador em caso de falha ao alocar memória. Você pode substituir esse comportamento padrão para que, quando malloc falhar ao alocar memória, malloc chame a nova rotina do manipulador da mesma forma que o operador new fará quando ele falhar pelo mesmo motivo. Para substituir o padrão, chame _set_new_mode(1); no início do programa ou vincule a newmode.obj.

Se um operator new definido pelo usuário for fornecido, as novas funções de manipulador não serão chamadas automaticamente em caso de falha.

Para obter mais informações, consulte new e delete na Referência de Linguagem C++.

Há um único manipulador _set_new_handler para todas as DLLs vinculadas dinamicamente ou executáveis em um único processo. Mesmo se você chamar _set_new_handler, o manipulador pode ser substituído por outro. Ou o novo manipulador pode substituir um manipulador definido por outra DLL ou executável no processo.

Requisitos

Função Cabeçalho necessário
_set_new_handler <new.h>

Para obter informações sobre compatibilidade, consulte Compatibilidade.

Exemplo

Neste exemplo, quando a alocação falhar, o controle será transferido para MyNewHandler. O argumento passado para MyNewHandler é o número de bytes solicitado. O valor retornado de MyNewHandler é um sinalizador que indica se a tentativa de alocação deve ser repetida: um valor diferente de zero indica que a tentativa de alocação deve ser repetida, enquanto um valor de zero indica que a alocação falhou.

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

Confira também

Alocação de memória
calloc
free
realloc