views:

1389

answers:

3

What are all the other things a new operator does other than allocating memory and calling a constructor?

A: 

Depends on if it's overloaded or not, if you built the app for debugging, if you're using a memory leak detector, if you have some kind of memory pooling scheme, if you have something like the Boehm garbage collector that's marking/unmarking bits, etc., etc. It could be doing a lot of custom stuff inside, or nothing special at all.

Michel
I think he covered that by stating "Standard"
Martin York
+11  A: 

The C++ standard has this to say about the single object form (the form usually used) of the new operator from the <new> header:

Required behavior:

Return a nonnull pointer to suitably aligned storage (3.7.3), or else throw a bad_alloc exception. This requirement is binding on a replacement version of this function.

Default behavior:

— Executes a loop: Within the loop, the function first attempts to allocate the requested storage. Whether the attempt involves a call to the Standard C library function malloc is unspecified.

— Returns a pointer to the allocated storage if the attempt is successful. Otherwise, if the last argument to set_new_handler() was a null pointer, throw bad_alloc.

— Otherwise, the function calls the current new_handler (18.4.2.2). If the called function returns, the loop repeats.

— The loop terminates when an attempt to allocate the requested storage is successful or when a called new_handler function does not return.

The standard has a lot of other stuff to say about the new operator and dynamic memory allocation (an awful lot to say), but I think the "Default behavior" list sums up the basics of the new operator pretty well.

Michael Burr
Is there anything like how the size of object is stored with the new.So that can be used when deleting the object using pointer
yesraaj
This is surely left for the implementation and will be different between platforms.
Anteru
That is not specified by the standard. Typically malloc() or something similar will be used and the size of the memory block will be kept using the same sort of techniques (or identical if malloc() is used).
Michael Burr
And if you're doing an array new/delete, the techniques used might be one of the ones discussed in the C++ FAQ Lite: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.14
Michael Burr
There's no need to store the size of the allocated block for single object new since the delete statement knows the size of the object and can thus free the right amount of space.
Motti
For polymorphic objects the destructor must be virtual and the compiler can use this in order to know the actual size of the object.
Motti
+5  A: 

I've written a explanation of what it does in this answer. It explains how

  • new gets the memory
  • new handles memory failure
  • new handles constructor exceptions
  • new handles special placement and nothrow versions

Michael explained how the default allocator function (::operator new) gets memory nicely and how it handles failure. I've seen your question on where the size of an object is stored in his comments. The answer is, there isn't size stored if not necassary. Remember that C doesn't need the size for free (and ::operator new can just use malloc):

void * memory = malloc(x);
free (memory); // no need to tell it the size

Here is an example where you see how storing the size has an impact on the size of allocation for the array form of a new expression (not covered by my other answer):

#include <cstddef>
#include <iostream>

struct f {
    // requests allocation of t bytes
    void * operator new[](std::size_t t) throw() {
        void *p = ::operator new[](t);
        std::cout << "new    p: " << p << std::endl;
        std::cout << "new size: " << t << std::endl;
        return p;
    }

    // requests deleting of t bytes starting at p
    void operator delete[](void *p, std::size_t t) throw() {
        std::cout << "delete p: " << p << std::endl;
        std::cout << "size    : " << t << std::endl;
        return ::operator delete[](p);
    }
};

int main() {
    std::cout << "sizeof f: " << sizeof (f) << std::endl;

    f * f_ = new f[1];
    std::cout << "&f_     : " << f_ << std::endl;
    delete[] f_;
}

It will print out something like this:

sizeof f: 1
new    p: 0x93fe008
new size: 5
&f_     : 0x93fe00c
delete p: 0x93fe008
size    : 5

One byte for the object itself and 4 bytes for the count which is stored just before the allocated area of the object. Now if we use the deallocation function without a size parameter (just removing it from the operator delete), we get this output:

sizeof f: 1
new    p: 0x9451008
new size: 1
&f_     : 0x9451008
delete p: 0x9451008

The C++ runtime here doesn't care about the size, so it doesn't store it anymore. Note that this is highly implementation specific, and that's what gcc does here to be able to tell you the size in the member operator delete. Other implementations may still store the size, and will most likely if there is a destructor to invoke for the class. For example just adding ~f() { } above makes gcc to store the size, regardless on what deallocation function we write.

Johannes Schaub - litb
Could you explain the syntax for this `operator delete[]` with size when implementing a memory pool, i.e. could you help me with http://stackoverflow.com/questions/2322742? Thanks!
Tobias