ARM Technical Support Knowledge Articles

How do I overload operator new?

Applies to: DS-5, RealView Development Suite (RVDS)

Answer

This FAQ introduces the basic concepts of overloading the new operators, and the effects of the ARM compiler option “--force_new_nothrow”.

The standard implementations of the new operators in the RVCT C++ libraries are suitable for general usage and are well implemented. Although it is not recommended to overload the new operators, there might be situations when you need to. Typical reasons include the following:

The three standard global new operators are as follows:

:: operator new(std::size_t size) throw(std::bad_alloc) /* operator new.
                        * It throws exceptions if the operation fails.*/
:: operator new(std::size_t size, const std::nothrow_t &) throw() /* nothrow new.
                        * It does not throw exceptions, but returns NULL.*/
:: operator new(std::size_t size, void *ptr) throw() /* placement new
(original).
                        * To alloc on a pre-known address. It is rarely used,

                        * and is prohibited to be replaced according to C++ Standard.*/

Furthermore there are three array new operators:

:: operator new[](std::size_t size) throw(std::bad_alloc)
:: operator new[](std::size_t size, const std::nothrow_t &) throw()
:: operator new[](std::size_t size, void *ptr) throw()

To overload the new operators you need to take care:

  1. If you write a non-normal form placement new, you need to write its corresponding delete. For example:

    Class A{
    public:
          ...
          static void * operator new(std::size_t size, std::ostream& logStream)
                                     throw(std::bad_alloc); // non-normal form placement new
          static void * operator delete(void *pMemory, std::ostream& logStream)
                                     throw(); // corresponding delete
    };

    A *pA = new(std::cerr) A; /* Without the corresponding delete, it is problomatic to 
                                          *
    use the non-normal form placement new.*/

    If an exception occurs during the new operation or the instance construction after the new operation, the memory manager in run-time will try to find the corresponding delete to release the memory. If it cannot find the correct delete, it will do nothing, therefore memory leaking will occur.

    The standard global delete operators are:

    ::operator delete(void *pMem) throw()
    ::operator delete(void *pMem, const std::nothrow_t &) throw()
    ::operator delete(void *pMem, void *ptr) throw()

    and
    ::operator delete[](void *pMem) throw()
    ::operator delete[](void *pMem, const std::nothrow_t &) throw()
    ::operator delete[](void *pMem, void *ptr) throw()
  2. Any overloaded class-specific new operators will hide the global new operators. For example:

    class CBase{
    public:
    ...
    static void* operator new(std::size_t size,                
    // this new hides the global
                           const std::nothrow_t & nt) throw(); // operator new(s)
    ...
    }

    CBase *pB = new(std::nothrow) CBase; // fine. CBase's nothrow new is called.
    CBase *pB = new CBase;
    // error! The normal form of global operator new is hidden.

  3. The new operators in a derived class will hide the global new operators and the base class new operators. For example:


    class CDerived:public CBase{
    public:
    ...
    static void* operator new(std::size_t size) throw(std::bad_alloc);
    }

    CDerived *pD = new(std::nothrow) CDerived; // error! CBase's nothrow new is hidden.
    CDerived *pD = new CDerived;
    // fine. CDerived's operator new is called.

  4. The nothrow operator new does not throw exceptions, instead it will return NULL if allocation fails.
    According to the ARM CPPABI[2], the functions overloading nothrow new MUST NOT examine its second argument.

  5. The ARM compiler has an option "--force_new_nothrow" that forces the use of the global nothrow new instead of the global operator new for all new invocations that do not use a second argument. The compiler will add the second argument (std::nothrow) to these operator new invocations during compilation. This is a non-standard implementation.
    For example by using "--force_new_nothrow" the ARM compiler will treat "new" as "no-throw new", which corresponds to "::operator new(std::size_t s, const std::nothrow_t&) throw();".

    Note: this does not affect the operator "new" calls within the RVCT C/C++ libraries, nor the class-specific operator "new". It is not recommended to use "--force_new_nothrow" in compilation[3].

  6. It might be worthwhile to consider rewriting malloc() function which is called in the implementation of new operators, instead of rewriting new operators directly. For more details please read Tailoring storage management.

Reference:

  1. Using the ::operator new function
  2. ARM CPPABI
  3. --force_new_nothrow
  4. Chapter 8 Customizing new and delete, Effective C++, Scott Meyers

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential