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