double delete

O

onsbomma

Hello

I know this is not good code, but i was wondering why dubble delete
gives an error (not an exception!!) and dubble free doesn't??
If new/delete works like malloc/free. Is the error caused by the
destructor?? and if so why???


Integer *m = (Integer*)malloc(sizeof(*m));
free(m);
free(m);

Integer *m = new Integer();
delete m;
delete m;


thx
 
P

Phlip

onsbomma said:
I know this is not good code, but i was wondering why dubble delete
gives an error (not an exception!!) and dubble free doesn't??
If new/delete works like malloc/free. Is the error caused by the
destructor?? and if so why???

Integer *m = (Integer*)malloc(sizeof(*m));
free(m);
free(m);

Integer *m = new Integer();
delete m;
delete m;

Because "undefined behavior" means anything could happen. Anything from the
program behaves the way you hope, to the nearest toilet explodes.

(If more implementations went with the latter, less C++ code out there would
suck.)

Mechanically, maybe free() doesn't call Integer's destructor, and maybe
calling that destructor twice bombs an internal pointer.
 
J

John Harrison

onsbomma said:
Hello

I know this is not good code, but i was wondering why dubble delete
gives an error (not an exception!!) and dubble free doesn't??

What sort of error? I don't think the code below should cause a compile
error.

If new/delete works like malloc/free. Is the error caused by the
destructor?? and if so why???

new/delete don't work exactly like malloc/free and the destructor is one
difference. It is possible that the destructor is causing the error
(whatever that is) but it would really depend on how the destructor was
written.
Integer *m = (Integer*)malloc(sizeof(*m));
free(m);
free(m);

Integer *m = new Integer();
delete m;
delete m;

Both if these pieces of code invoke what is known as undefined behaviour. It
is a concept that some people have trouble getting to grips with, but
basically it says that if you do something that is against the rules of C++
(in this case freeing/deleting the same memory twice) then the behaviour of
your code is completely undefined. It might crash, it might output an error,
it might throw an exception, it might format you hard drive, etc. etc.
Anything might happen, INCLUDING it might work.

john
 
H

Howard

JKop said:
Integer* p_m = reinterpret_cast< Integer* const & > ( malloc(...


-JKop

Why are you casting a void* (from malloc) to a const reference to an
Integer* (whatever the heck an "Integer" is)? Why not just cast to an
Integer*, since that's the type being assigned to?

-Howrad
 
A

Andre Kostur

JKop said:
Integer* p_m = reinterpret_cast< Integer* const & > ( malloc(...

Why you want want to ever obfuscate your code like that? What is the
"const &" portion really contributing to the expression (functionally, not
the langauage definition.)? Or, as a rephrase, why in this specific
instance is the const ref desirable and/or necessary? What additional and
useful expressiveness does your method have over:

Integer * m = reinterpret_cast<Integer *>(malloc(sizeof(Integer)));

(I would hope there would be a placement new call somewhere later.....)
 
J

JKop

Howard posted:
Why are you casting a void* (from malloc) to a const reference to an
Integer* (whatever the heck an "Integer" is)? Why not just cast to an
Integer*, since that's the type being assigned to?

-Howrad


reinterpret_cast< Integer* const & >

reinterpret_cast< Integer* >

reinterpret_cast< Integer * const >


Either will do.


I suppose I chose the first as it's the most "complete" in that it
yields an l-value. There's also less likelyhood of the formation of a
temporary.


-JKop
 
R

Rob Williscroft

JKop wrote in in comp.lang.c++:
Integer* p_m = reinterpret_cast< Integer* const & > ( malloc(...

Your replacment for the well formed static_cast isn't legal C++
you can't cast an rvalue to an lvalue.

Rob.
 
H

Howard

JKop said:
Howard posted:



reinterpret_cast< Integer* const & >

reinterpret_cast< Integer* >

reinterpret_cast< Integer * const >


Either will do.


I suppose I chose the first as it's the most "complete" in that it
yields an l-value. There's also less likelyhood of the formation of a
temporary.

I don't understand this at all. You're simply initializing a pointer. The
call to malloc returns a void*, which is used to directly initialize an
Integer*. There are no constructors or anything involved here that might
cause unwanted copies of objects to be created. And what do you mean that
it "yields an l-value"? And how does that help anything?

I think you've gotten WAY too hung up on references and const. Keep It
Simple, umm, Sir. :)

(By the way, isn't a static_cast the normal cast used with malloc? Assuming
you've got some reason to not use new in the first place, that is?)
 
R

red floyd

Howard said:
[redacted]
reinterpret_cast< Integer* const & >

reinterpret_cast< Integer* >

reinterpret_cast< Integer * const >
[redacted]

why not use static_cast? A void* can be static_cast'ed to any other
pointer type. i.e.

// do not this. use new Integer or new Integer[...] instead!!!!
Integer* some_ptr = static_cast<Integer*>(malloc(...));
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,518
Latest member
RomanGratt

Latest Threads

Top