sailing

Everything...

shining cento in book reading: handle out of memory problem for new operator -by register a global SetNewHandler


Template/inheritance based NewHandler support, a good solution to add memory allocation failure support at class level
the template is used to provide unique currentHandler pointer for each class, the inheritance is to provide newhandler support for the class
So, if you want to have your own class support new handler, do it like the code below:

    
        template<class T>				// "mixin-style" base class
        class NewHandlerSupport {			// for class-specific
        public:						// set_new_handler support
        
      static new_handler set_new_handler(new_handler p);
        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)
        {
        new_handler globalHandler =
        std::set_new_handler(currentHandler);
        
      void *memory;
        
      try {
        memory = ::operator new(size);
        }
        catch (std::bad_alloc&) {
        std::set_new_handler(globalHandler);
        throw;
        }
        
      std::set_new_handler(globalHandler);
        
      return memory;
        }
        


client code without template:

    void noMoreMemory();                           // decl. of function to
        // call if memory allocation
        // for X objects fails
        
    X::set_new_handler(noMoreMemory);
        // set noMoreMemory as X's
        // new-handling function
        
    X *px1 = new X;                                // if memory allocation
        // fails, call noMoreMemory
        
    string *ps = new string;                       // if memory allocation
        // fails, call the global
        // new-handling function
        // (if there is one)
        
    X::set_new_handler(0);                         // set the X-specific
        // new-handling function
        // to nothing (i.e., null)
        
    X *px2 = new X;                                // if memory allocation
        // fails, throw an exception
        // immediately. (There is
        // no new-handling function
        // for class X.)
    Client code for the template version:
    template<class T>
        new_handler NewHandlerSupport<T>::currentHandler
     


    "no throw" support for old compiler based code, return 0 instead of exception under insufficient memory situation

    Until 1993, C++ required that operator new return 0 when it was unable to satisfy a memory request. The current behavior is for operator new to throw a std::bad_alloc exception, but a lot of C++ was written before compilers began supporting the revised specification. The °C++ standardization committee didn't want to abandon the established test-for-0 code base, so they provided alternative forms of operator new (and operator new[] — see Item 8 that continue to offer the traditional failure-yields-0 behavior. These forms are called "nothrow" forms because, well, they never do a throw, and they employ nothrow objects (defined in the standard header <new>) at the point where new is used:   
    class Widget { ... };
        
    Widget *pw1 = new Widget;      // throws std::bad_alloc if
        // allocation fails
        
    if (pw1 == 0) ...              // this test must fail
        
    Widget *pw2 =
        new (nothrow) Widget;        // returns 0 if allocation
        // fails
        
    if (pw2 == 0) ...              // this test may succeed
        

posted on 2007-03-16 01:50  乌生鱼汤  阅读(375)  评论(0)    收藏  举报

导航