HOWTO: Overload New to Reduce Memory Fragmentation

Last reviewed: October 3, 1997
Article ID: Q139638
The information in this article applies to:
  • Microsoft Visual C++, 32-bit Edition, versions 2.0, 2.1, 2.2, 4.0, 5.0

SUMMARY

Providing a dedicated heap by overloading new and delete for a class can significantly reduce memory fragmentation. Any class that is frequently instantiated using new is a candidate for providing a dedicated heap.

This method works best when many instances of a class are used in close time proximity but random order. For example, this method will work well for a newly created list that is about to be sorted.

This method impairs performance where the use of instances of the class is more time proximate to the use of other heap-allocated objects. For example, this method would impair the performance of a scrolling, in-memory view of rows read from a database.

There is no easy substitute for careful analysis of locality of reference, where locality is gauged according to the page size used by the host operating system's virtual memory management and time separation.

This technique should not be applied to a base class that can be or might be derived from if data is to be added to the derived class.

MORE INFORMATION

The following sample code stores the dedicated heap handle in the static member variable m_hHeap. The heap handle is initialized to NULL in the Classdemo.cpp file. When a class object is instantiated using new, the overloaded new is called. If the handle is NULL, the heap is created. If the handle is not NULL, HeapAlloc is called to allocate the requested size.

Sample Code

   /* Compile options needed: none
   */
   /* Classdemo.h file  */

   #ifndef    __CLASSDEMO_H__
   #define    __CLASSDEMO_H__

   #include   <windows.h>

   class  ClassDemo
   {
      // private member vars and functions for ClassDemo class

      static  HANDLE      m_hHeap; // fixed heap handle
      int     m_nMyData[100];      // class data

   public:
      // public member functions for ClassDemo class
      // declaration of new & delete operator overloads
      void*   operator    new(unsigned int nSize);
      void    operator    delete(void* pObj);
      static  void        HeapCreate();
   };

   #define    INITIAL_HEAP_SIZE   4096    // initial heap size
   #define    CLASS_DEMO_OBJS_MAX 100000  // max number of objects used

   inline void*   ClassDemo::operator new(unsigned int nSize)
   {  // allocate memory using fixed heap
      if  (m_hHeap == NULL)   // if NULL, needs to be created
      {
          HeapCreate();       // create heap

          if  (m_hHeap == NULL)
          {
              return NULL;    // HeapCreate failed
          }
      }

      // return pointer to allocated memory
      return  HeapAlloc(m_hHeap, 0, nSize);
   }

   inline void    ClassDemo::operator delete(void* pObj)
   {  // free memory from fixed heap
      HeapFree(m_hHeap, 0, pObj);
   }

   #endif //  __CLASSDEMO_H__
   /* End of Classdemo.h file  */

   /* Classdemo.cpp file  */
   #include   <stdio.h>
   #include   "ClassDemo.h"

   HANDLE     ClassDemo::m_hHeap = NULL;  // Initialize handle

   void   ClassDemo::HeapCreate()
   {
      int nRet = IDRETRY;                          // message box return
      int nSize = CLASS_DEMO_OBJS_MAX * sizeof(ClassDemo);// max heap size

      m_hHeap = ::HeapCreate(0,                    // heap flags
                  INITIAL_HEAP_SIZE,               // initial size of heap
                  nSize);                          // max heap size

      while   ((m_hHeap == NULL) && (nRet != IDIGNORE))
      {       // keep trying until no error or user ignores
          char    szMsg[80];                       // message buffer

          // format message
          sprintf(szMsg, "Could allocate a heap of size %d", nSize);
          // Display error
          nRet = MessageBox(NULL, szMsg, NULL,
                            MB_ABORTRETRYIGNORE | MB_TASKMODAL);

          if  (nSize < sizeof(ClassDemo))
          {
              return; // heap would be too small to be usefull, return
          }

          switch  (nRet)
          {
              case    IDABORT:  // user selected abort
              {
                  abort();
              }

              case    IDIGNORE: // user selected ignore
              {
                  return;
              }

              default:  // user selected retry, the message box could not
              {         // be displayed, or unknown return code
                  nSize /= 2;  // try a smaller request

                  m_hHeap = ::HeapCreate(
                              0,                  // heap flags
                              INITIAL_HEAP_SIZE,  // initial size of heap
                              nSize);             // max heap size
                  break;
              }
          }
      }
   }
   /*  End of Classdemo.cpp file  */


Additional query words: Windows 95 10.00 10.10 10.20
Keywords : CPPLngIss CRTIss kbcode
Version : WINNT:2.0,2.1,2.2,4.0,5.0;
Platform : NT WINDOWS
Issue type : kbhowto


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: October 3, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.