Share via


_set_new_handler

new 演算子がメモリの割り当てに失敗した場合は、独自のエラー処理機構に制御を移します。 Microsoft C++ コンパイラでは、この関数を使用して標準ライブラリに実装 std::set_new_handler します。

構文

_PNH _set_new_handler( _PNH pNewHandler );

パラメーター

pNewHandler
アプリケーションによって提供されたメモリ処理関数へのポインター。 引数 0 を指定するか nullptr 、新しいハンドラーを削除します。

戻り値

_set_new_handler によって登録された前の例外処理関数へのポインターを返し、前の関数を後で復元できるようにします。 前の関数が設定されていない場合は、戻り値を使用して既定の動作を復元できます。 この値には nullptr 、0 を指定できます。

解説

C++ の _set_new_handler 関数は、new 演算子がメモリの割り当てに失敗した場合に制御を取得する例外処理関数を指定します。 new が失敗した場合、ランタイム システムは _set_new_handler への引数として渡された例外処理関数を自動的に呼び出します。 _PNH<new.h>定義されている 、型を返し、型 intsize_t引数を受け取る関数へのポインターです。 size_t を使用して、割り当てられる領域の量を指定します。

既定のハンドラーはありません。

_set_new_handler は本質的に、ガベージ コレクション スキームです。 ランタイム システムは、関数がゼロ以外の値を返すたびに割り当てを再試行し、関数がゼロを返すと失敗します。

プログラム内に _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 が指定されている場合、失敗した場合、新しいハンドラー関数は自動的に呼び出されません。

詳細については、「C++ 言語リファレンス」を参照newdeleteしてください。

1 つの _set_new_handler プロセスで、動的にリンクされているすべての DLL または実行可能ファイルに対して 1 つのハンドラーがあります。 呼び出 _set_new_handlerしても、ハンドラーが別のハンドラーに置き換えられる可能性があります。 または、新しいハンドラーは、プロセス内の別の DLL または実行可能ファイルによって設定されたハンドラーを置き換えることができます。

必要条件

機能 必須ヘッダー
_set_new_handler <new.h>

互換性の詳細については、「 Compatibility」を参照してください。

この例では、割り当てが失敗すると、制御が MyNewHandler. 渡される MyNewHandler 引数は、要求されたバイト数です。 返される MyNewHandler 値は、割り当てを再試行するかどうかを示すフラグです。0 以外の値は割り当てを再試行する必要があることを示し、0 の値は割り当てが失敗したことを示します。

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

関連項目

メモリ割り当て
calloc
free
realloc