Condividi tramite


_set_new_handler

Trasferisce il controllo al meccanismo di gestione degli errori se l'operatore new non riesce ad allocare la memoria. Il compilatore Microsoft C++ usa questa funzione per implementare std::set_new_handler nella libreria standard.

Sintassi

_PNH _set_new_handler( _PNH pNewHandler );

Parametri

pNewHandler
Puntatore alla funzione di gestione della memoria fornita dall'applicazione. Un argomento pari a 0 o nullptr fa sì che il nuovo gestore venga rimosso.

Valore restituito

Restituisce un puntatore alla funzione di gestione delle eccezioni precedente registrata da _set_new_handler, in modo che la funzione precedente possa essere ripristinata in un secondo momento. Se non è stata impostata alcuna funzione precedente, è possibile usare il valore restituito per ripristinare il comportamento predefinito. Questo valore può essere nullptr o 0.

Osservazioni:

La funzione C++ _set_new_handler viene usata per specificare una funzione di gestione delle eccezioni che deve assumere il controllo se l'operatore new non riesce ad allocare memoria. Se new ha esito negativo, il sistema di runtime chiama automaticamente la funzione di gestione delle eccezioni passata come argomento di _set_new_handler. _PNH, definito in <new.h>, è un puntatore a una funzione che restituisce il tipo int e accetta un argomento di tipo size_t. Usare size_t per specificare la quantità di spazio da allocare.

Non esiste alcun gestore predefinito.

_set_new_handler è fondamentalmente uno schema di garbage collection. Il sistema di runtime ritenta l'allocazione ogni volta che la funzione restituisce un valore diverso da zero e non riesce se la funzione restituisce 0.

Un'occorrenza della funzione _set_new_handler in un programma registra la funzione di gestione delle eccezioni specificata nell'elenco di argomenti con il sistema di runtime:

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

Per impostazione predefinita, lo _set_new_handler stato globale della funzione è limitato all'applicazione. Per modificarlo, vedere Stato globale in CRT.

È possibile salvare l'indirizzo dell'ultima funzione passata alla funzione _set_new_handler e crearne un'altra istanza in seguito:

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

La funzione C++ _set_new_mode imposta la nuova modalità del gestore per malloc. La nuova modalità del gestore indica se, in caso di errore, malloc deve chiamare la routine del nuovo gestore come impostato da _set_new_handler. Per impostazione predefinita, malloc non chiama la nuova routine del gestore in caso di errore di allocazione della memoria. È possibile eseguire l'override di questo comportamento predefinito in modo che, quando malloc non riesce ad allocare memoria, malloc chiami la routine del nuovo gestore, come fa l'operatore new quando non riesce per lo stesso motivo. Per eseguire l'override dell'impostazione predefinita, chiamare _set_new_mode(1); all'inizio del programma o collegare con newmode.obj.

Se viene specificato un oggetto definito dall'utente operator new , le nuove funzioni del gestore non vengono chiamate automaticamente in caso di errore.

Per altre informazioni, vedere new e delete nella Guida di riferimento al linguaggio C++.

Esiste un singolo _set_new_handler gestore per tutte le DLL collegate dinamicamente o i file eseguibili in un singolo processo. Anche se si chiama _set_new_handler, il gestore potrebbe essere sostituito da un altro. In alternativa, il nuovo gestore può sostituire un gestore impostato da un'altra DLL o eseguibile nel processo.

Requisiti

Funzione Intestazione obbligatoria
_set_new_handler <new.h>

Per altre informazioni sulla compatibilità, vedere Compatibility (Compatibilità).

Esempio

In questo esempio, quando l'allocazione non riesce, il controllo viene trasferito a MyNewHandler. L'argomento passato a MyNewHandler è il numero di byte richiesti. Il valore restituito da è un flag che indica se l'allocazione deve essere ritentata: un valore diverso da MyNewHandler zero indica che l'allocazione deve essere ritentata e un valore zero indica che l'allocazione non è riuscita.

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

Vedi anche

Allocazione di memoria
calloc
free
realloc