_set_new_handler

Transfere o controle ao mecanismo de gerenciamento de erros se o operador new não conseguir alocar memória. O compilador do 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.

Valor retornado

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 usa um argumento do tipo size_t. Use size_t para especificar a quantidade de espaço a ser alocado.

Não há nenhum 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 _set_new_handler estado global da função tem como escopo o aplicativo. Para alterá-lo, consulte o 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 C++ _set_new_mode define o novo modo de 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 por 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 com newmode.obj.

Se um usuário definido operator new 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 _set_new_handler manipulador para todas as DLLs vinculadas dinamicamente ou executáveis em um único processo. Mesmo se você chamar _set_new_handler, seu manipulador pode ser substituído por outro. Ou, seu novo manipulador pode substituir um manipulador definido por outra DLL ou executável em seu processo.

Requisitos

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

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

Exemplo

Neste exemplo, quando a alocação falha, o controle é transferido para MyNewHandler. O argumento passado é MyNewHandler o número de bytes solicitados. O valor retornado MyNewHandler é um sinalizador que indica se a alocação deve ser repetida: um valor diferente de zero indica que a alocação deve ser repetida e um valor 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