メモリが確保できないときのデフォルトの処理
malloc
NULLを返す
new
std::bad_alloc例外を投げる。
_set_new_handler
_set_new_handlerを使うと、newでメモリが確保できなかったとき呼ばれる関数(ハンドラ)を指定できる。この関数はガーベージコレクションとして使われることが想定されていて、0以外を戻すと再度メモリ確保が試みされて失敗すればまたハンドラが呼ばれる。0を返すと失敗で、std::bad_alloc例外が投げられる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include <new.h> #include <iostream> #include <limits> #define NOMINMAX #include <Windows.h> using namespace std; #define STATUS_INSUFFICIENT_MEM 0xE0000001 // https://msdn.microsoft.com/en-us/library/het71c37.aspx int OnNoMemory(size_t size) { cout << "OnNoMemory:" << size << endl; //ULONG_PTR exception_args[] = {size}; //::RaiseException(STATUS_INSUFFICIENT_MEM, // EXCEPTION_NONCONTINUABLE, // sizeof(exception_args)/sizeof(exception_args[0]), // exception_args); // non 0 means success static int ret = 5; return --ret; } int main() { int64_t largesize = std::numeric_limits<int64_t>::max(); void* vp = malloc(largesize); // returns NULL; try { char* p = new char[largesize]; // case throw std::bad_alloc() delete[] p; } catch (std::bad_alloc&) { cout << "std::bad_alloc" << endl; } auto prevhandler = _set_new_handler(OnNoMemory); // prevhander is NULL vp = malloc(largesize); // returns NULL try { char* p = new char[largesize]; delete[] p; } catch (std::bad_alloc&) { // if OnNoMemory returns 0, here it comes. cout << "std::bad_alloc" << endl; } cout << "Hello World!" << endl; return 0; } |
上記ソースでは試していないが、_set_new_mode(1)を呼べば、mallocのときでも同様の処理ができるようだ。