473,395 Members | 1,468 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

new and delete

Hi,
Below is a small code about memory allocation and deallocation.

#include <cstdlib>
#include <iostream>
using namespace std;

class X {
public:
void* operator new(size_t sz) throw (const char*) {
void* p = malloc(sz); //LINE1
if (p == 0) throw "malloc() failed";
return p;
}

void operator delete(void* p) {
free(p);
}

};

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl; //LINE2
free(p);
};

};

int main() {
X* ptr = new X; //LINE3

// call X::operator delete(void*)
delete ptr;

Y* yptr = new Y;

// call Y::operator delete(void*, size_t)
// with size of Y as second argument
delete yptr; //LINE4
}
My questions are:
When LINE3 is executed, LINE1 is executed. How is the variable sz
assigned sizeof(X)?

The output of the code is:
Freeing 400 byte(s)
When LINE4 is executed, LINE2 is executed. How does sz get the value
400?

Thanks a lot.

Jack

Jun 22 '06 #1
10 1853

<ju******@gmail.com> wrote in message
news:11**********************@r2g2000cwb.googlegro ups.com...
Hi,
Below is a small code about memory allocation and deallocation.

#include <cstdlib>
#include <iostream>
using namespace std;

class X {
public:
void* operator new(size_t sz) throw (const char*) {
void* p = malloc(sz); //LINE1
if (p == 0) throw "malloc() failed";
return p;
}

void operator delete(void* p) {
free(p);
}

};

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl; //LINE2
free(p);
};

};

int main() {
X* ptr = new X; //LINE3

// call X::operator delete(void*)
delete ptr;

Y* yptr = new Y;

// call Y::operator delete(void*, size_t)
// with size of Y as second argument
delete yptr; //LINE4
}
My questions are:
When LINE3 is executed, LINE1 is executed. How is the variable sz
assigned sizeof(X)?

The output of the code is:
Freeing 400 byte(s)
When LINE4 is executed, LINE2 is executed. How does sz get the value
400?


It's magic! :-)

Actually, the C++ standard doesn't specify how or where new and delete keep
this information stored. That's up to the people who wrote the compiler to
decide. Most likely, some code is executed "behind the scenes" which
determines the size of the object to be created, and stores it in a "hidden"
location, for use later when deleting. (I suppose you could try checking
the generated machine code and see exactly what it's doing.)

-Howard


Jun 22 '06 #2
ju******@gmail.com wrote:
Below is a small code about memory allocation and deallocation.

#include <cstdlib>
#include <iostream>
using namespace std;

class X {
public:
void* operator new(size_t sz) throw (const char*) {
void* p = malloc(sz); //LINE1
if (p == 0) throw "malloc() failed";
return p;
}

void operator delete(void* p) {
free(p);
}

};

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl; //LINE2
free(p);
};

};

int main() {
X* ptr = new X; //LINE3

// call X::operator delete(void*)
delete ptr;

Y* yptr = new Y;

// call Y::operator delete(void*, size_t)
// with size of Y as second argument
delete yptr; //LINE4
}
My questions are:
When LINE3 is executed, LINE1 is executed. How is the variable sz
assigned sizeof(X)?
Compiler magic.
The output of the code is:
Freeing 400 byte(s)
When LINE4 is executed, LINE2 is executed. How does sz get the value
400?


Compiler magic.

The 'operator new' and 'operator delete' are called by the executing
environment when you use the "new expression". There are intervening
mechanisms that know how much to pass to *your* 'new'.

Put a breakpoint in your 'operator new' and examine the call stack
under the debugger, when the execution is suspended. YOu will see
something between the 'main' and 'operator new', most likely. What
it is, isn't defined in the language. But it will be there.

You might find "Inside the C++ Object Model" by Lippman worth a look.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 22 '06 #3
ju******@gmail.com wrote:
Hi,
Below is a small code about memory allocation and deallocation.

#include <cstdlib>
#include <iostream>
using namespace std;

class X {
public:
void* operator new(size_t sz) throw (const char*) {
void* p = malloc(sz); //LINE1
if (p == 0) throw "malloc() failed";
return p;
}

void operator delete(void* p) {
free(p);
}

};

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl; //LINE2
free(p);
};

};

int main() {
X* ptr = new X; //LINE3

// call X::operator delete(void*)
delete ptr;

Y* yptr = new Y;

// call Y::operator delete(void*, size_t)
// with size of Y as second argument
delete yptr; //LINE4
}
My questions are:
When LINE3 is executed, LINE1 is executed. How is the variable sz
assigned sizeof(X)?

The output of the code is:
Freeing 400 byte(s)
When LINE4 is executed, LINE2 is executed. How does sz get the value
400?

Thanks a lot.

Jack


A footnote to what Howard and Victor said: your class Y doesn't have a
custom new operator defined to match its delete operator. Consequently,
the default global new is used for creating your Y object, but the
object is deleted by your custom delete, which uses free(). This is
bad. See the FAQ:

http://www.parashift.com/c++-faq-lit....html#faq-16.3

See also _C++ Coding Standards_ by Sutter and Alexandrescu, Item 45.

Cheers! --M

Jun 22 '06 #4


A footnote to what Howard and Victor said: your class Y doesn't have a
custom new operator defined to match its delete operator. Consequently,
the default global new is used for creating your Y object, but the
object is deleted by your custom delete, which uses free(). This is
bad. See the FAQ:


Thanks. Now I free() by delete as the NEWLINE in the code below. Do you
think it is correct?

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::delete (Y*) p; //NEWLINE
};

};

Jun 22 '06 #5
ju******@gmail.com wrote:
...
Thanks. Now I free() by delete as the NEWLINE in the code below. Do you
think it is correct?

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::delete (Y*) p; //NEWLINE
};

};


No, this is not correct. In general case delete-expression does several
different things in sequence, one (and only one) of which is calling
your 'operator delete'. Here you inserted another delete-expression into
your 'operator delete's implementation. This will cause the whole
process to start all over again, which in general will lead to
unpredictable consequences. For example, the code will potentially make
an attempt to call the destructor of the object twice - first time from
the external delete-expression and second time from that
delete-expression you inserted into the 'operator delete'.

What you were trying to do in this case can be expressed correctly as
follows

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::operator delete(p, sz); //NEWLINE
};
};

Note, that in this case instead of invoking another delete-expression,
we simply call the global 'operator delete' explicitly. I hope you
understand the difference between the two.

--
Best regards,
Andrey Tarasevich
Jun 22 '06 #6
Thanks.

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::operator delete(p, sz); //NEWLINE
};
};

But it can not pass compiling. Below is the error:

new-delete.cc: In static member function `static void Y::operator
delete(void*,
unsigned int)':
new-delete.cc:31: error: invalid conversion from `size_t' to `void*'
new-delete.cc:31: error: initializing argument 2 of `void operator
delete(void*, void*)'

It seems to me that the compiler parses NEWLINE as Y::operator
delete(void*,
unsigned int).

When I change it into the code below, it works.
::operator delete(p); //NEWLINE

Is the second argument sz necessary? By the way, the global operator
delete does not invoke destructor, right?

Jack

Jun 22 '06 #7
ju******@gmail.com wrote:

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::operator delete(p, sz); //NEWLINE
};
};
But it can not pass compiling. Below is the error:

new-delete.cc: In static member function `static void Y::operator
delete(void*,
unsigned int)':
new-delete.cc:31: error: invalid conversion from `size_t' to `void*'
new-delete.cc:31: error: initializing argument 2 of `void operator
delete(void*, void*)'

It seems to me that the compiler parses NEWLINE as Y::operator
delete(void*,
unsigned int).

When I change it into the code below, it works.
::operator delete(p); //NEWLINE

Is the second argument sz necessary?


You are right. The standard library does not provide global 'operator
delete' with size argument. That's why it doesn't compile. You can call
the '::operator delete(p)' instead.
By the way, the global operator
delete does not invoke destructor, right?


'operator delete' functions _never_ invoke destructors. These are raw
memory management functions. Delete-expressions call destructors,
'operator delete' fucntion don't. These are two different things. You
seem to be mixing the two.

--
Best regards,
Andrey Tarasevich
Jun 22 '06 #8

"Andrey Tarasevich" <an**************@hotmail.com> wrote in message
news:12*************@news.supernews.com...
ju******@gmail.com wrote:
...
Thanks. Now I free() by delete as the NEWLINE in the code below. Do you
think it is correct?

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::delete (Y*) p; //NEWLINE
};

};


No, this is not correct. In general case delete-expression does several
different things in sequence, one (and only one) of which is calling
your 'operator delete'. Here you inserted another delete-expression into
your 'operator delete's implementation. This will cause the whole
process to start all over again, which in general will lead to
unpredictable consequences. For example, the code will potentially make
an attempt to call the destructor of the object twice - first time from
the external delete-expression and second time from that
delete-expression you inserted into the 'operator delete'.

What you were trying to do in this case can be expressed correctly as
follows

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::operator delete(p, sz); //NEWLINE
};
};

Note, that in this case instead of invoking another delete-expression,
we simply call the global 'operator delete' explicitly. I hope you
understand the difference between the two.


I thought the problem was that he's missing a new operator for the Y class.
Wouldn't the correct solution be to add that, not modify his delete
operator?

-Howard


Jun 22 '06 #9
Howard wrote:
...
What you were trying to do in this case can be expressed correctly as
follows

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::operator delete(p, sz); //NEWLINE
};
};

Note, that in this case instead of invoking another delete-expression,
we simply call the global 'operator delete' explicitly. I hope you
understand the difference between the two.


I thought the problem was that he's missing a new operator for the Y class.
Wouldn't the correct solution be to add that, not modify his delete
operator?
...


Well, it depends on how you see it. I'd say that the actual problem was
that the memory deallocation function he used in his 'operator delete'
was potentially unrelated to the memory allocation function used by the
standard '::operator new'. Re-delegating the actual deallocation to the
standard '::operator delete' solved the problem.

Whether having a user-defined deallocation function without providing a
user-defined allocation function is a good style is a separate issue.

--
Best regards,
Andrey Tarasevich
Jun 22 '06 #10

"Andrey Tarasevich" <an**************@hotmail.com> wrote in message
news:12*************@news.supernews.com...
Howard wrote:
...
What you were trying to do in this case can be expressed correctly as
follows

class Y {
int filler[100];
public:

// two arguments
void operator delete(void* p, size_t sz) throw (const char*) {
cout << "Freeing " << sz << " byte(s)" << endl;
//free(p);
::operator delete(p, sz); //NEWLINE
};
};

Note, that in this case instead of invoking another delete-expression,
we simply call the global 'operator delete' explicitly. I hope you
understand the difference between the two.


I thought the problem was that he's missing a new operator for the Y
class.
Wouldn't the correct solution be to add that, not modify his delete
operator?
...


Well, it depends on how you see it. I'd say that the actual problem was
that the memory deallocation function he used in his 'operator delete'
was potentially unrelated to the memory allocation function used by the
standard '::operator new'. Re-delegating the actual deallocation to the
standard '::operator delete' solved the problem.

Whether having a user-defined deallocation function without providing a
user-defined allocation function is a good style is a separate issue.


Ah, ok. I thought maybe the operator new would be *required* in this case.
I keep learning...

Thanks, and regards,
-Howard

Jun 22 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Dave | last post by:
Hello all, In the code below, I see the following output: base::operator new(size_t, int) base::base() base::~base() base::operator delete(void *) In the case of an exception being thrown...
1
by: Nimmi Srivastav | last post by:
There's a rather nondescript book called "Using Borland C++" by Lee and Mark Atkinson (Que Corporation) which presents an excellent discussion of overloaded new and delete operators. In fact there...
3
by: Nimmi Srivastav | last post by:
There's a rather nondescript book called "Using Borland C++" by Lee and Mark Atkinson (Que Corporation) which presents an excellent discussion of overloaded new and delete operators. I am...
1
by: Douglas Peterson | last post by:
class Allocator { public: virtual void * Alloc(size_t) = 0; virtual void * Free(void*) = 0; }; class Object { public:
2
by: Dave | last post by:
Hello all, I'd like to find a source on the web that discusses, in a comprehensive manner and in one place, everything about new / delete. It should include overloading operator new, the new...
3
by: silver360 | last post by:
Hello, I'm trying to create a basic Heap manager and i have some question about new/delete overloading. The following code give me this output : >> $./heap >> registered : 0x804d098 >>...
9
by: rohits123 | last post by:
I have an overload delete operator as below ////////////////////////////////// void operator delete(void* mem,int head_type) { mmHead local_Head = CPRMemory::GetMemoryHead(head_type);...
10
by: jeffjohnson_alpha | last post by:
We all know that a new-expression, foo* a = new foo() ; allocates memory for a single foo then calls foo::foo(). And we know that void* p = ::operator new(sizeof(foo)) ; allocates a...
15
by: LuB | last post by:
I am constantly creating and destroying a singular object used within a class I wrote. To save a bit of time, I am considering using 'placement new'. I guess we could also debate this decision -...
29
by: =?Utf-8?B?R2Vvcmdl?= | last post by:
Hello everyone, I remembered delete is implemented through operator overloading, but I am not quite clear. Could anyone recommend some links about how delete is implemented so that I can...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.