Sdílet prostřednictvím


_set_new_handler

Přenese řízení do mechanismu zpracování chyb, pokud new operátor nepřidělí paměť. Kompilátor Jazyka Microsoft C++ používá tuto funkci k implementaci std::set_new_handler ve standardní knihovně.

Syntaxe

_PNH _set_new_handler( _PNH pNewHandler );

Parametry

pNewHandler
Ukazatel na funkci zpracování paměti dodané aplikací. Argument 0 nebo nullptr způsobí odebrání nové obslužné rutiny.

Vrácená hodnota

Vrátí ukazatel na předchozí funkci zpracování výjimek registrovanou _set_new_handlerfunkcí , aby předchozí funkce byla později obnovena. Pokud nebyla nastavena žádná předchozí funkce, můžete k obnovení výchozího chování použít návratová hodnota. Tato hodnota může být nullptr nebo 0.

Poznámky

Funkce jazyka C++ _set_new_handler určuje funkci zpracování výjimek, která získá kontrolu, pokud new operátor nepřidělí paměť. Pokud new selže, systém za běhu automaticky volá funkci zpracování výjimek, která byla předána jako argument _set_new_handler. _PNH, definovaný v <new.h>, je ukazatel na funkci, která vrací typ int a přebírá argument typu size_t. Slouží size_t k určení množství místa, které se má přidělit.

Neexistuje žádná výchozí obslužná rutina.

_set_new_handler je v podstatě schéma uvolňování paměti. Systém za běhu opakuje přidělení pokaždé, když funkce vrátí nenulovou hodnotu a selže, pokud vaše funkce vrátí hodnotu 0.

Výskyt _set_new_handler funkce v programu zaregistruje funkci zpracování výjimek zadanou v seznamu argumentů v systému za běhu:

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

Ve výchozím nastavení _set_new_handler je globální stav funkce vymezený na aplikaci. Pokud ho chcete změnit, přečtěte si téma Globální stav v CRT.

Adresu funkce, která byla naposledy předána _set_new_handler funkci, můžete uložit a později ji znovu obnovit:

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

Funkce C++ _set_new_mode nastaví nový režim obslužné rutiny pro malloc. Nový režim obslužné rutiny označuje, zda při selhání malloc je volání nové rutiny obslužné rutiny nastavena ._set_new_handler Ve výchozím nastavení nevolá rutinu nové obslužné rutiny při malloc selhání přidělení paměti. Toto výchozí chování můžete přepsat tak, aby při malloc selhání přidělení paměti malloc volaly novou rutinu obslužné rutiny stejným způsobem jako new operátor v případě selhání z stejného důvodu. Chcete-li přepsat výchozí, zavolejte _set_new_mode(1); v rané fázi programu nebo odkaz s newmode.obj.

Pokud je zadán uživatel definovaný operator new , nové funkce obslužné rutiny nejsou automaticky volána při selhání.

Další informace najdete new delete v referenční dokumentaci jazyka C++.

V jednom procesu existuje jedna _set_new_handler obslužná rutina pro všechny dynamicky propojené knihovny DLL nebo spustitelné soubory. I když zavoláte _set_new_handler, může být obslužná rutina nahrazena jinou. Nebo může nová obslužná rutina nahradit obslužnou rutinu nastavenou jinou knihovnou DLL nebo spustitelným souborem v procesu.

Požadavky

Function Požadovaný hlavičkový soubor
_set_new_handler <new.h>

Další informace o kompatibilitě najdete v tématu Kompatibilita.

Příklad

V tomto příkladu, když přidělení selže, řízení se přenese do MyNewHandler. Argument předaný MyNewHandler je počet požadovaných bajtů. Vrácená hodnota MyNewHandler je příznak označující, jestli se má znovu opakovat přidělení: nenulová hodnota indikuje, že přidělení by se mělo opakovat, a nulová hodnota označuje, že přidělení selhalo.

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

Viz také

Přidělení paměti
calloc
free
realloc