Sign in to follow this  

new and delete not called correctly

This topic is 4341 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have some problems with new and delete, and I wonder if I have understood the standard incorrectly or MSVC2005 doesn't implement this specific part correctly. On page 80 (5.3.4) in the standard (I talk about the C++ standard, ISO/IEC 14882:2003) it says:
Quote:
new-placement: ( expression-list )
So I expect the following to be a "new-placement":
void* operator new(size_t size, int dummy)
{
    return ::operator new(size);
}
Similary I expect the following to be a "delete-placement":
void operator delete(void* address, int dummy)
{
    ::operator delete(address);
}
Now on page 82-83 (5.3.4.20) the standard says:
Quote:
If a new-expression calls a deallocation function, it passes the value returned from the allocation function call as the first argument of type void*. If a placement deallocation function is called, it is passed the same additional arguments as were passed to the placement allocation function, that is, the same arguments as those specified with the new-placement syntax. If the implementation is allowed to make a copy of any argument as part of the call to the allocation function, it is allowed to make a copy (of the same original value) as part of the call to the deallocation function or to reuse the copy made as part of the call to the allocation function. If the copy is elided in one place, it need not be elided in the other.
If I understand this correctly it means that if I called the new-placement, I declared earlier, like this:
int* i = new(3) int;
Then that would mean that the following:
delete i;
Would call my delete-placement with dummy set to 3, the problem is that it doesn't work. I tried to create a little test program so you can see it for yourself:
#include <iostream>

void* operator new(size_t size,int dummy)
{
	std::cout << "new(size_t = " << size <<", int = " << dummy << ")" << std::endl;
	return ::operator new(size);
}
void operator delete(void* address,int dummy)
{
	std::cout << "delete(void* = " << address <<", int = " << dummy << ")" << std::endl;
	::operator delete(address);
}

int main()
{   
	int* a = new(6) int;
	delete a;

	return 0;
}

My output is:
new(size_t = 4, int = 6)
But delete-placement isn't called, could anyone please tell me if I have misunderstood the C++ standard? Also I found this article which also claims delete-placement should be called. Look in the bottom where it says:
Quote:
Thing *tp = new (buf) Thing( arg ); In this case, the appropriate operator delete is the two-argument version corresponding to the overloaded operator new used for the allocation of Thing; operator delete( void *, Buffer &), and this is the version the runtime system will invoke.

Share this post


Link to post
Share on other sites
Quote:

If a new-expression calls a deallocation function, it passes the value returned from the allocation function call as the first argument of type void*. If a placement deallocation function is called, it is passed the same additional arguments as were passed to the placement allocation function, that is, the same arguments as those specified with the new-placement syntax. If the implementation is allowed to make a copy of any argument as part of the call to the allocation function, it is allowed to make a copy (of the same original value) as part of the call to the deallocation function or to reuse the copy made as part of the call to the allocation function. If the copy is elided in one place, it need not be elided in the other.


A new-expression, as per 5.3.4.1, is the actual expression:
::opt new new-placementopt new-type-id new-initializeropt

The above section does not cover deallocations that occur outside an expression of the above form. Section 5.3.4.17 (and the article you quote) says that a deallocation would occur in this expression when the constructor throws an exception When that happens, the correct deallocation function will be called, assuming that it can be unambiguously found.

The deallocation function used in a delete cast-expression situation is described in 3.7.3.2, and my understanding is that the ad hoc usual class deallocator will be called and, if unavailable, the global usual deallocator will be called instead.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk


How did I miss that? Thanks for the help though. Does anyone know how to call a delete-placement without putting the address in parentheses. i don't care if I have to do something like this:
delete(all,the,arguments) pointer;
As long as I don't have to add anything (a ')' ) to the right of "pointer".

Share this post


Link to post
Share on other sites
Well... the following probably contains a destructor-related bug, but I think it could be modified to work correctly:


class myDelete {
const int i;
public:
myDelete( int i ) : i( i ) { }
template<typename T>
myDelete & operator<<( T* ptr ) {
if( ptr ) ptr->~T( );
::operator delete( ptr, i );
return *this;
}
};

Foo* foo = new (18) Foo(42);
myDelete (18) << foo;

// And while we're at it:

#define del(x) myDelete(x) <<

del (18) foo;




EDIT: in fact, the above should be correct, destructor-wise (that is, it would work and not work under the same conditions as delete).

Share this post


Link to post
Share on other sites

This topic is 4341 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this