_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_handler
funkcí , 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
*/