_set_new_handler
若 new
運算子無法配置記憶體,則將控制項傳送至您的錯誤處理機制。 Microsoft C++編譯程式會使用此函式在標準連結庫中實 std::set_new_handler
作。
語法
_PNH _set_new_handler( _PNH pNewHandler );
參數
pNewHandler
應用程式所提供記憶體處理函式的指標。 0 的自變數,或 nullptr
導致移除新的處理程式。
傳回值
傳回 _set_new_handler
所註冊之先前例外狀況處理函式的指標,因此,稍後可以還原先前函式。 如果未設定任何先前的函式,則傳回值可用來還原預設行為。 此值可以是 nullptr
或 0。
備註
如果 new
運算子無法配置記憶體,則 C++ _set_new_handler
函式會指定取得控制權的例外狀況處理函式。 如果 new
失敗,執行階段系統會自動呼叫傳遞為 _set_new_handler
之引數的例外狀況處理函式。 _PNH
,定義於 <new.h>
中,是傳回型 int
別並接受 型 size_t
別自變數之函式的指標。 使用 size_t
來指定要配置的空間量。
沒有預設處理程式。
_set_new_handler
基本上是記憶體回收配置。 每次函式傳回非零值時,執行階段系統都會重試配置,如果函式傳回 0 則失敗。
程式中出現的 _set_new_handler
函式會向執行階段系統註冊引數清單中所指定的例外狀況處理函式:
// _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];
}
根據預設,函 _set_new_handler
式的全域狀態會限定於應用程式。 若要變更它,請參閱 CRT中的全域狀態。
您可以儲存最後傳遞至 _set_new_handler
函式的函式位址,並稍後進行恢復:
_PNH old_handler = _set_new_handler( my_handler );
// Code that requires my_handler
// . . .
_set_new_handler( old_handler )
// Code that requires old_handler
// . . .
C++函式 _set_new_mode
會設定 的新處理程式模式 malloc
。 新的處理常式模式表示失敗時,malloc
是否呼叫 _set_new_handler
所設定的新處理常式。 根據預設, malloc
不會在無法配置記憶體時呼叫新的處理程式例程。 您可以覆寫這個預設行為,因此,在 malloc
無法配置記憶體時,malloc
會呼叫新的處理常式,其方法與 new
運算子因相同原因而失敗時所執行的方法相同。 若要覆寫預設值,請在程式早期呼叫 _set_new_mode(1);
,或使用 連結 newmode.obj
。
如果提供使用者定義 operator new
,新的處理程式函式不會在失敗時自動呼叫。
如需詳細資訊,請參閱 new
C++ 語言參考中的 和 delete
。
單一進程中所有動態連結 DLL 或可執行檔都有單 _set_new_handler
一處理程式。 即使您呼叫 _set_new_handler
,您的處理程式也可能由另一個取代。 或者,您的新處理程式可能會取代進程中另一個 DLL 或可執行檔所設定的處理程式。
需求
函式 | 必要的標頭 |
---|---|
_set_new_handler |
<new.h> |
如需相容性詳細資訊,請參閱相容性。
範例
在這裡範例中,當設定失敗時,控制權會傳送至 MyNewHandler
。 傳遞至 MyNewHandler
的自變數是要求的位元元組數目。 傳 MyNewHandler
回的值是旗標,指出是否應該重試配置:非零值表示應該重試配置,而零值表示配置失敗。
// 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
*/