メモリ割り当て異常のset_new_handler


演算子newがオブジェクトにメモリを割り当てるのに十分な連続メモリブロックが見つからない場合、何が起こりますか?new-handlerという関数が呼び出されます.
new-handlerのデフォルトの動作は例外を放出します.しかし、プログラム内でスタックで割り当てる場合は、少なくともnew-handlerの代わりに「メモリが切れた」情報を使用し、プログラムを異常に中断します.この方法では,プログラムをデバッグする際にプログラムエラーの手がかりが得られる.
NEWを含めることで.H、そして私たちが読み込みたい関数アドレスをパラメータとしてset_を呼び出しますnew_handler()関数は、new-handlerを置き換えます.
typedef void (*new_handler)(); 
new_handler set_new_handler(new_handler p) throw(); 

見えますnew_handlerは、入力パラメータも戻り値もない関数を指すカスタム関数ポインタタイプです.
set_new_handlerは入力でnew_を返しますhandlerタイプの関数です.set_new_handlerの入力パラメータはoperator newがメモリの割り当てに失敗したときに呼び出すエラー処理関数のポインタで、戻り値はset_new_handlerが呼び出されない前から機能していた古いエラー処理関数のポインタ.
#include
#include
#include
void __cdecl newhandler()
{
   cout << "The new_handler is called:"<< endl;
   throw bad_alloc();
   return;
}
int main()
{
   set_new_handler (newhandler);
   try
   {
      while (1)
      {
         new int[5000000];
         cout << "Allocating 5000000 ints."<< endl;
      }
   }
   catch ( exception e )
   {
      cout << e.what() << "xxx"<< endl;
   }
}
プログラム出力:
Allocating 5000000 ints.
       ……
Allocating 5000000 ints.
The new_handler is called:
bad allocation
以上の例のプログラムはVC 6にある.0環境ではコンパイルできませんがdev_c++ではコンパイルでき,試したことはないがgccでも同様に実現できると信じている.VC 6であれば.0環境でコンパイルするには、_set_new_handler(MSDNのこの関数の使用説明を参照)はset_ではなくnew_handler、次はVC 6です.0次の例です.
#include
#include
#include//ヘッダファイルが重要
int __cdecl memory(size_t)/戻りタイプとパラメータタイプに注意
{
cout<<メモリ切れ!<    exit(0);
}
void main()
{  
   ::_set_new_handler(memory);//パラメータとして関数ポインタを渡す
    while ( 1 )
      {
         new int[5000000];
         cout << "Allocating 5000000 ints."<< endl;
      }
}
プログラム出力:
Allocating 5000000 ints.
       ……
Allocating 5000000 ints.
メモリ切れ!
設計されたnew-handler関数は、次の機能の1つを実装する必要があります.
より多くの使用可能なメモリを生成:operator newの次のメモリ割り当ての試みが成功する可能性があります.このポリシーを実装する方法の1つは、プログラムの起動時に大きなメモリブロックを割り当て、new-handlerを最初に呼び出したときに解放することです.メモリ数が少なすぎるなど、ユーザーへの警告情報が解放されると、次回のリクエストが失敗する可能性があります.これ以上空き領域がない限り.
別のnew-handler関数をインストールします.現在のnew-handler関数がより多くの使用可能なメモリを生成できない場合は、別のnew-handler関数がより多くのリソースを提供できることを知っている可能性があります.これにより、現在のnew-handlerは、set_new_handlerを呼び出すことによって、それに代わる別のnew-handlerをインストールすることができる.次のoperator newでnew-handlerを呼び出すと、最近インストールしたものが使用されます.(このポリシーのもう一つの変更方法は、new-handlerが独自の動作を変更できるようにすることです.次に呼び出すと、異なることをします.方法は、new-handlerが自身の動作に影響を与える静的またはグローバルデータを変更できるようにすることです.
new-handlerを取り外します.つまり、空のポインタをset_に渡します.new_handler.new-handlerがインストールされていない場合、operator newの割り当てメモリが失敗すると、標準的なstd::bad_が放出されます.allocタイプの異常.
スローstd::bad_allocまたはstd::bad_allocが継承する他のタイプの例外:このような例外はoperator newに捕捉されないため、最初にメモリリクエストを行った場所に送られます.(別の異なるタイプの例外を投げ出すとoperator new例外仕様に違反します.仕様のデフォルトの動作はabortを呼び出すので、new-handlerが例外を投げ出す場合は、std::bad_allocから継承されていると確信してください.
返されません:abortまたはexitを呼び出すのが一般的です.abort/exitは標準cライブラリで入手できます
転載先:http://zhaoweizhuanshuo.blog.163.com/blog/static/14805526220108545937329/