For Programmers: Free Programming Magazines  


Home > Archive > VC Language > January 2006 > Re: Overloading new









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Re: Overloading new
Igor Tandetnik

2006-01-24, 7:07 pm

maynard <pfrye@spsu.edu> wrote:
> void *myClass::operator new[](size_t sz, long numpts)
> {
> sz /= sizeof(myClass);


Be aware that the size of the allocation request may be (and almost
always is) larger than size of one element times the number of elements.
You cannot reliably determine the number of elements being allocated.

> myClass *x = ::new myClass[sz];


This is a very bad idea - you are invoking undefined behavior. First,
operator new is supposed to allocate raw memory block of the specified
size. After it returns, the compiler runs constructors over this memory.
But you here already cause constructors to be run, so you are
double-constructing Nothing good can come of it.

Second, the pointer returned by new[] expression may not point to the
beginning of the allocated memory, and usually doesn't. Again, the
compiler usually requests more memory than would be occupied by the
elements themselves. It stores certain housekeeping information (at
least, the number of the elements allocated) at the beginning of the
block, and returns a pointer that points right after this internal data.

By way of example, suppose the compiler needs 4 bytes at the beginning
of a block, and sizeof(myClass) == 8. The program contains this
statement:

myClass *x = new(42) myClass[10];

The compiler calls your operator new[] passing 84 (4 + 10*8) for the
size and 42 for the second parameter. You calculate sz to be 10 (you got
lucky this time, but imagine that myClass is only two bytes large) and
call ::new myClass[10].

This time the compiler calls built-in operator new[] requesting the same
84 bytes of memory. It stores 10 in the first four bytes, runs myClass
constructor ten times at offsets 4, 12, 20 and so on and returns a
pointer that is offset 4 bytes into the buffer. You then return that
offset pointer from your method. The compiler assumes that you have
allocated 84 bytes, stores 10 in the first 4 bytes (which are actually
at offset 4, so now 10 is stored twice) and runs myClass constructor at
what it thinks are offsets 4, 12, 20 and so on but are in fact offsets
8, 16, 24 and so on.

So by now you have constructors run twice on overlapping blocks of
memory, you have a buffer overrun, and when the program will eventually
call delete[] it will do so with a wrong pointer.

Bottom line: the only thing operator new can do is allocate raw memory.
There's no point writing anything into this memory (except perhaps
filling it with a distinct bit pattern for debugging purposes) - it will
essentially be wiped out and repaved when constructors are run.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com