Knowing new[]'s overhead in a compiler-independent way
Knowing new[]'s overhead in a compiler-independent way
In C++, the array version of new allocates some extra storage space alongside the allocated object, so that it may store the array's size in order to call each element's destructor later.
My question is : is there a clean, compiler-agnostic way to know about the size of the actually allocated object (overhead included) without actually performing the allocation ?
The only option which I currently see is to create a special version of operator new[] for that purpose, which takes a size_t reference as a parameter, stores the result in it, and always returns NULL. Not exactly what I'd call clean, as it creates some very confusing syntax. ("Wait a minute, why does he use placement new here to do... err... what ?")
Any better idea ?
My question is : is there a clean, compiler-agnostic way to know about the size of the actually allocated object (overhead included) without actually performing the allocation ?
The only option which I currently see is to create a special version of operator new[] for that purpose, which takes a size_t reference as a parameter, stores the result in it, and always returns NULL. Not exactly what I'd call clean, as it creates some very confusing syntax. ("Wait a minute, why does he use placement new here to do... err... what ?")
Any better idea ?
Last edited by Neolander on Tue Jul 05, 2011 10:26 am, edited 1 time in total.
Re: Knowing new[]'s overhead in a compiler-independent way
But why would you try to optimize new, and introduce a special new that may break with other code?
And I seriously doubt that extra tidy size, along with other possible header and footer, make a sensible different in terms of memory footprint for array of elements,
and the related processing time is neglectable compare with the actual memory allocation.
it is meant to be isolated from compiler, so your question on "compiler-agnostic" way, well, the whole business is compiler-agnostic.
To determinate the size, check the library source code.
And I seriously doubt that extra tidy size, along with other possible header and footer, make a sensible different in terms of memory footprint for array of elements,
and the related processing time is neglectable compare with the actual memory allocation.
memory allocation routines (new) are defined in the stdc++ library, and can be replaced.My question is : is there a clean, compiler-agnostic way to know about the size of the actually allocated object (overhead included) without actually performing the allocation ?
it is meant to be isolated from compiler, so your question on "compiler-agnostic" way, well, the whole business is compiler-agnostic.
To determinate the size, check the library source code.
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: Knowing new[]'s overhead in a compiler-independent way
...the size-of-array header is added by the compiler, not the library.
Also, be aware: if your operator new returns NULL, std::bad_alloc will be thrown.
Also, be aware: if your operator new returns NULL, std::bad_alloc will be thrown.
Re: Knowing new[]'s overhead in a compiler-independent way
@Owen : Nope, because I have followed berkus' advice of putting a throw() somewhere in my allocator declarations User-space new and delete will probably be standards-compliant and have full exception support, but at kernel level I want neither exceptions nor the hurdle of playing with nothrow objects all the time, so standards be damned...
@bluemoon : As Owen says, the situation is not this simple. When you write...
...four things happen :
So before operator new[] is called, there is no obvious way to know how much memory will actually have to be allocated by it. And for what I want to do (avoiding multiple allocations by allocating one big buffer and slicing it in bits), this is a problem. Hence my question : is there a clean way to know, without performing any allocation, how much memory a new[] will eat up ? A way that does not involve dirty hacks like an overloaded new[] that looks like a placement new and doesn't actually allocate memory...
@bluemoon : As Owen says, the situation is not this simple. When you write...
Code: Select all
Foo* bar = new Foo[5]();
delete[] bar;
- Memory for the array is allocated
- Each Foo in the array is initialized
- Each Foo in the array is destroyed
- Memory for the array is freed
So before operator new[] is called, there is no obvious way to know how much memory will actually have to be allocated by it. And for what I want to do (avoiding multiple allocations by allocating one big buffer and slicing it in bits), this is a problem. Hence my question : is there a clean way to know, without performing any allocation, how much memory a new[] will eat up ? A way that does not involve dirty hacks like an overloaded new[] that looks like a placement new and doesn't actually allocate memory...
Re: Knowing new[]'s overhead in a compiler-independent way
...and the compiler will slice it in whatever way applicable.
I think you're on a wild goose chase here.
I think you're on a wild goose chase here.
Every good solution is obvious once you've found it.
Re: Knowing new[]'s overhead in a compiler-independent way
Code: Select all
static bool initializing = false;
static size_t overhead = 0;
void *operator new[](size_t sz) {
if (initializing) {
overhead = sz;
return (void*)~0UL;
} else {
// Do normal memory allocation
}
}
void init() {
initializing = true;
volatile void *x = new int[0];
initializing = false;
}
Re: Knowing new[]'s overhead in a compiler-independent way
I think this is the option I'd end up choosing, save for some tweaking. Still a bit ugly, but better than my idea.JamesM wrote:?Code: Select all
static bool initializing = false; static size_t overhead = 0; void *operator new[](size_t sz) { if (initializing) { overhead = sz; return (void*)~0UL; } else { // Do normal memory allocation } } void init() { initializing = true; volatile void *x = new int[0]; initializing = false; }
Last edited by Neolander on Wed Jul 06, 2011 4:31 am, edited 1 time in total.
Re: Knowing new[]'s overhead in a compiler-independent way
I want to know how much memory is needed by a new[] before actually allocating the memory The idea is that in a scenario where I'd have to allocate lots of related small heap objects that will also be freed at the same time (strings, typically), I can (and need to) get much better performance by calculating the amount of required memory and allocating everything at once.berkus wrote:I honestly don't follow what's the problem. Your operator new[] implementation will be called with exactly how many bytes are needed, including the overhead.
Re: Knowing new[]'s overhead in a compiler-independent way
Last time I played around overloading new for some memory management/tracking software, if I did a new char[10], it would ask my new for exactly 10 bytes. (When I say overloaded, I don't mean a single overload for a class, just overloaded generic new/delete). As far as I know, new doesn't have much overhead over than what is used by whatever malloc implementation it calls, which is obviously dependant on your particular malloc. I could be wrong (wouldn't be the first time), but unless you use something with GC (garbage collection) new shouldn't need any extra space. If you're writing an OS, you are probably going to have to use your own NEW implementation anyways, so it's up to you what overhead it has. If you are using a cross compiled GCC, look at the sources to see if it doesn't anything special for new. I'm not really sure what overhead you are talking about or looking to avoid (overhead as in cpu cycles, or in memory footprint).
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: Knowing new[]'s overhead in a compiler-independent way
..try "new SomeTypeWithADestructor[10]"
- blobmiester
- Member
- Posts: 45
- Joined: Fri Jul 16, 2010 9:49 am
Re: Knowing new[]'s overhead in a compiler-independent way
Which will translate into (theoretically equivalent) (SomeTypeWithADestructor*)malloc(sizeof (SomeTypeWithADestructor) * 10).Owen wrote:..try "new SomeTypeWithADestructor[10]"
The destructor/constructor calling is handled by the compiler at new/delete for the type.
As for new[]'s overhead. The compiler doesn't decide what it is. The implementation of operator new() does. There is no possible way to detect this or control it -- unless you write your own malloc/new implementation (which isn't that hard if you are caring this much about allocation speed).
On second thought, you could just malloc() a pool of memory and use placement new/delete to allocate (which is what the STL does). That is what I'd do.
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: Knowing new[]'s overhead in a compiler-independent way
If it translates into that, how does delete [] thatBuffer know how many destructors it needs to run? Conclusion: It doesn't translate into that.blobmiester wrote:Which will translate into (theoretically equivalent) (SomeTypeWithADestructor*)malloc(sizeof (SomeTypeWithADestructor) * 10).Owen wrote:..try "new SomeTypeWithADestructor[10]"
It translates into ::operator new[](some value > sizeof (T) * 10).
To start writing things in pseudo-C++0X, the compiler-side logic for new probably looks something like the following:
Code: Select all
T* buf;
if(alignof(T) > alignof(size_t)) {
buf = ::operator new(sizeof(T) * (nElements + 1));
size_t* count = (size_t*) &buf[0];
*count = nElements;
buf += 1;
} else {
size_t* count = ::operator new(sizeof(T) * nElements + sizeof(size_t));
buf = (T*) count[1];
*count = nElements;
}
for(size_t i = 0; i < nElements; i++) buf[i]->T();
return buf
Re: Knowing new[]'s overhead in a compiler-independent way
And this is exactly what I got in practice ! Good to know that new[] avoids wasting space on types without a destructor though
(Ah, a deep breath of 'net after some internet-less holidays)
(Ah, a deep breath of 'net after some internet-less holidays)