1,當operator new無法滿足內存需求時,拋出std::bad_alloc.
下面是一個驗證的代碼:
- #include <iostream>
- #include <stdexcept>
- using namespace std ;
- int main ()
- {
- try
- {
- int* p=NULL;
- while(1)
- p=new int[10000];
- }catch(std::bad_alloc&)
- {
- cout<<"no enough mem."<<endl;
- }
- return 0 ;
- }
2,C++的一個公約:
當operator new無法滿足需求時,它會在拋出exception前先調用一個專屬的錯誤處理函數.
我們稱之為:new-handler.
3,當operator無法滿足內存需求時,它會不只一次的調用new-handler函數;
它會不斷的重復調用,直到找到足夠的內存.
一個設計良好的new-handler函數必須完成下面幾件事:
(1)讓更多內存可用.
例如:事先在程序起始處配置一大塊內存,然后在new-handler第一次被調用時釋放之.
(2)配置另外一個new-handler,其手上握有比較多的資源.
(3)卸除new-handler,set_new_handler(NULL)
將不再調用專屬函數,而直接拋出exception.
(4)拋出exception.
(5)不回返,直接調用abort()或exit.
- #include <iostream>
- #include <stdexcept>
- using namespace std ;
- void noMoreMemory()
- {
- cout<<"Unable to satify request for memory."<<endl;
- //原則(5):不回返
- abort();//不加,將會是一個死循環.
- //原則(4):也可以通過拋出一個異常
- //throw std::bad_alloc();
- }
- int main ()
- {
- //typedef void (*new_handler)(); 頭文件中已經給出
- //設定自己的專屬錯誤處理函數.
- //返回之前的new_handler
- new_handler old_new_handler=set_new_handler(noMoreMemory);
- //set_new_handler(NULL); //卸除new-handler,拋出異常.
- try
- {
- int* p=NULL;
- while(1)
- p=new int[10000];
- }catch(std::bad_alloc&)
- {
- cout<<"no more memory."<<endl;
- set_new_handler(old_new_handler);
- }
- set_new_handler(old_new_handler);
- return 0 ;
- }
4,設定類class專屬的new-handler.
一個強大的類模板.
- #include <iostream>
- #include <stdexcept>
- using namespace std ;
- template<class T>
- class NewHandlerSupport
- {
- public:
- static new_handler set_new_handler(new_handler p);
- static void* operator new(size_t size);
- static void* operator new[](size_t size);
- private:
- static new_handler currentHandler;
- };
- template<class T>
- new_handler NewHandlerSupport<T>::set_new_handler(new_handler p)
- {
- new_handler oldHandler=currentHandler;
- currentHandler=p;
- return oldHandler; //返回之前的專屬函數
- }
- template<class T>
- void* NewHandlerSupport<T>::operator new(size_t size)
- {
- //下面調用標準的set_new_handler
- new_handler globalHandler=std::set_new_handler(currentHandler);
- void* memory;
- try
- {
- //使用標準的new.
- memory=::operator new(size);
- }catch(std::bad_alloc)
- {
- std::set_new_handler(globalHandler);
- throw; //繼續拋出異常
- }
- std::set_new_handler(globalHandler); //返回原來的設置
- return memory; //返回之前的專屬函數
- }
- template<class T>
- static void* NewHandlerSupport<T>::operator new[](size_t size)
- {
- return operator new(size);
- }
- template<class T>
- new_handler NewHandlerSupport<T>::currentHandler; //設置為0
- void noMoreMemory()
- {
- cout<<"Unable to satify request for memory."<<endl;
- //abort();
- throw std::bad_alloc();
- }
- class X : public NewHandlerSupport<X>
- {
- };
- int main ()
- {
- X::set_new_handler(noMoreMemory);
- try
- {
- X* p=NULL;
- //先調用專屬函數,然后有專屬函數拋出異常.
- while(1)
- p=new X[100000];
- }catch(std::bad_alloc&)
- {
- cout<<"no more memory."<<endl;
- }
- X::set_new_handler(0);
- try
- {
- X* p=NULL;
- //不再調用專屬函數,直接捕獲異常.
- while(1)
- p=new X[100000];
- }catch(std::bad_alloc&)
- {
- cout<<"no more memory."<<endl;
- }
- return 0 ;
- }
5,舊的編譯器:
如果內存配置失敗不會拋出異常,只是返回0.
測試實例:
int* p=new (nothrow)int;
if(p==0)
cout<<"memory error;"<<endl;