delete POD array - on which platforms does it not work?

M

Martin T.

Hi all!

char* p = new char[n]; // POD!
....
delete[] p; // std compliant
delete p; // will work on VC8
free(p); // will also work on VC8


I am interested on which platforms/compilers the second two statements
would not work. (access violation or mem-leak).

thanks!
br,
Martin
 
V

Vaclav Haisman

Martin T. wrote, On 2.4.2008 7:30:
Hi all!

char* p = new char[n]; // POD!
...
delete[] p; // std compliant
delete p; // will work on VC8
free(p); // will also work on VC8


I am interested on which platforms/compilers the second two statements
would not work. (access violation or mem-leak).
Why does it matter? It is wrong C++ even if it compiles and works.
 
K

Krice

delete p; // will work on VC8
free(p); // will also work on VC8

Are you sure these don't mess up anything in VC8?
Anyway this question is braindead. You use delete[]
for arrays and never free() with operator new.
 
M

Martin T.

Krice said:
Are you sure these don't mess up anything in VC8?

Yes, 100% sure.
Anyway this question is braindead. You use delete[]
for arrays and never free() with operator new.

This is question is quite valid. Indeed it becomes more valid with
answers such as this. I could also rephrase it:
Is it (just) *really* evil, or does anyone know of a platform where it
will break for PODs?

br,
Martin
 
A

Andrey Tarasevich

Martin said:
Yes, 100% sure.

Wrong. Mixing different kinds of allocator/deallocator functions will
not work on any platform in general case. That applies to VC8 as well.
The memory allocation functions hiding behind these new/delete
expressions can be overloaded completely independently, leading to
disastrous results in the above code samples.

Remember, new/delete, new[]/delete[] and malloc/free are three
alternative and completely independent memory allocation approaches,
which bear absolutely no relation to each other. For this reason, they
can't be mixed in the above manner.
 
K

Kai-Uwe Bux

Martin said:
Krice said:
Are you sure these don't mess up anything in VC8?

Yes, 100% sure.
Anyway this question is braindead. You use delete[]
for arrays and never free() with operator new.

This is question is quite valid. Indeed it becomes more valid with
answers such as this. I could also rephrase it:
Is it (just) *really* evil,

There is nothing evil about it. It is just undefined behavior.
or does anyone know of a platform where it
will break for PODs?

It is undefined behavior on any platform. That makes it somewhat hard to
produce a test case.


Best

Kai-Uwe Bux
 
J

Juha Nieminen

Martin said:
Yes, 100% sure.

How can you be so sure? Are you sure that they don't, for example,
leak memory? Did you use some kind of profiler to check this or something?
 
Y

Yannick Tremblay

Hi all!

char* p = new char[n]; // POD!
...
delete[] p; // std compliant
delete p; // will work on VC8
free(p); // will also work on VC8


I am interested on which platforms/compilers the second two statements
would not work. (access violation or mem-leak).

Philosophically, the question is somewhat interesting and as other
posters have already answer, this is undefined behavior.

On Linux using g++ 4:
#include <cstdlib>
int main()
{
char* p = new char[100]; // POD!
delete[] p; // std compliant
char *q = new char[100];
delete q; // will work on VC8
char *r = new char[100];
free(r); // will also work on VC8
return 0;
}

valgrind reports the following errors:
==17797== Mismatched free() / delete / delete []
==17797== at 0x4004E56: operator delete(void*)
(vg_replace_malloc.c:244)
==17797== by 0x8048552: main (newdelete.cpp:7)
==17797== Address 0x40290C0 is 0 bytes inside a block of size 100
alloc'd
==17797== at 0x400595C: operator new[](unsigned)
(vg_replace_malloc.c:195)
==17797== by 0x8048541: main (newdelete.cpp:6)
==17797==
==17797== Mismatched free() / delete / delete []
==17797== at 0x400513F: free (vg_replace_malloc.c:233)
==17797== by 0x8048570: main (newdelete.cpp:9)
==17797== Address 0x4029158 is 0 bytes inside a block of size 100
alloc'd
==17797== at 0x40595C: operator new[](unsigned)
(vg_replace_malloc.c:195)
==17797== by 0x804855F: main (newdelete.cpp:8)

I don't know if it would damage my heap per se but valgrind is
noticing a problem with the compiled code.

Practically however: I do not remember the last time I used new[]. I
honestly never use it. In the huge huge huge majority of cases,
"std::vector<int>(n)" will do better than "new int[n]".

I find "new" useful, albeit rarely, but "new[]", virtually never.

Yan
 
T

Triple-DES

  How can you be so sure? Are you sure that they don't, for example,
leak memory? Did you use some kind of profiler to check this or something?

The _CrtDumpMemoryLeaks() function can be used when running under the
debugger. I too tried this, and was unable to produce a memory leak on
VC8.

Without further evidence, I wouldn't go as far as saying that this is
100% safe on VC8, but it would seem that the most trivial cases are
handled gracefully.

DP
 
M

Martin T.

Yannick said:
Hi all!

char* p = new char[n]; // POD!
...
delete[] p; // std compliant
delete p; // will work on VC8
free(p); // will also work on VC8


I am interested on which platforms/compilers the second two statements
would not work. (access violation or mem-leak).

Philosophically, the question is somewhat interesting and as other
posters have already answer, this is undefined behavior.

On Linux using g++ 4:
#include <cstdlib>
int main()
{
char* p = new char[100]; // POD!
delete[] p; // std compliant
char *q = new char[100];
delete q; // will work on VC8
char *r = new char[100];
free(r); // will also work on VC8
return 0;
}

valgrind reports the following errors:
==17797== Mismatched free() / delete / delete []
==17797== at 0x4004E56: operator delete(void*)
(vg_replace_malloc.c:244)
==17797== by 0x8048552: main (newdelete.cpp:7)
==17797== Address 0x40290C0 is 0 bytes inside a block of size 100
alloc'd
==17797== at 0x400595C: operator new[](unsigned)
(vg_replace_malloc.c:195)
==17797== by 0x8048541: main (newdelete.cpp:6)
==17797==
==17797== Mismatched free() / delete / delete []
==17797== at 0x400513F: free (vg_replace_malloc.c:233)
==17797== by 0x8048570: main (newdelete.cpp:9)
==17797== Address 0x4029158 is 0 bytes inside a block of size 100
alloc'd
==17797== at 0x40595C: operator new[](unsigned)
(vg_replace_malloc.c:195)
==17797== by 0x804855F: main (newdelete.cpp:8)

I don't know if it would damage my heap per se but valgrind is
noticing a problem with the compiled code.

Of course. Valgrind should report it.
Practically however: I do not remember the last time I used new[]. I
honestly never use it. In the huge huge huge majority of cases,
"std::vector<int>(n)" will do better than "new int[n]".

I find "new" useful, albeit rarely, but "new[]", virtually never.

Have you ever compared the performance of std::vector<int>(n) vs. new
int[n] (in a release build, but without optimization?)
My results are somewhere factor 5 on VC8 (VS2005) in favor of new[].
I agree though - I do not use new[] except in the classes that hide it
from me.
Also - technically the (2003) std does not guarantee that the memory of
std::vector is allocated contiguously, right?

thanks for your comments,
br,
Martin
 
M

Martin T.

Andrey said:
Wrong. Mixing different kinds of allocator/deallocator functions will
not work on any platform in general case. That applies to VC8 as well.
The memory allocation functions hiding behind these new/delete
expressions can be overloaded completely independently, leading to
disastrous results in the above code samples.
Of course if the memory allocation functions for the POD in question be
overloaded, then it would break with high probability.
For most projects I have worked with though, this can be ruled out. (I'm
sure there are some very valid examples where it's used.)

Make it 100% sure (for VC8) when new/delete are not overloaded for the POD.
Remember, new/delete, new[]/delete[] and malloc/free are three
alternative and completely independent memory allocation approaches,
which bear absolutely no relation to each other. For this reason, they
can't be mixed in the above manner.

As I see it, they are independent in the standard and it's undefined
behavior according to that.
However, my question was (and I'm sure there are): On which
platform/compiler *implementations* will code such as this break in
release code. (break = access violation or memory leak)

br,
Martin
 
M

Martin T.

Krice said:
GCC and VC++ free edition (is that 2005?). There you go.

The current version of the VC++ free edition is 2008 (VC9 I believe) and
I have a hard time believing that it will break there. Care to explain
how it breaks there (in the absence of overloaded allocation)?

br,
Martin
 
M

Martin T.

Kai-Uwe Bux said:
Martin T. wrote:

....

It is undefined behavior on any platform. That makes it somewhat hard to
produce a test case.

Well, I am sure the standard says something about the outcome of a
delete[] for PODs ... ?
So, if the outcome of the free(new char[n]) is the same, one could say
it does not break in this specific implementation, right?

br,
Martin
 
Y

Yannick Tremblay

Yannick said:
Of course. Valgrind should report it.

hmm, given that valgrind only has the compile code, not the source,
then something must be different as a result on what it does. But
regardless, it is nice that valgrind spots and report it.
Practically however: I do not remember the last time I used new[]. I
honestly never use it. In the huge huge huge majority of cases,
"std::vector<int>(n)" will do better than "new int[n]".

I find "new" useful, albeit rarely, but "new[]", virtually never.

Have you ever compared the performance of std::vector<int>(n) vs. new
int[n] (in a release build, but without optimization?)

Why would I not want to let the compiler optimize the code?

This is a typical C hand coder way of opting out: "C++ is slow. Look I
compile with debugs and no optimization and std::vector::at() is 10x
slower than accessing a malloc'ed array and std::vector::push_back()
is 50x slower than memcpy".
My results are somewhere factor 5 on VC8 (VS2005) in favor of new[].

Try again with optimization on. You will probably find:

std::vector<int>(n) is a bit slower than new int[n] but not much

std::vector<int>(n) is about the same speed as
int * p = new int[n]; memset(p,0, n * sizeof(int));

it is hard to measure the speed difference between: accessing data i a
std::vector using operator[] and in a new'ed array using [].

It is a bit slower to access data using vector::at() but if you turn
on optimisation, it might be hard to notice.

try for example Stepanov containers benchmark:
http://www.stepanovpapers.com/container_benchmark.cpp

On my machine, the performance of vectors is typically better than
that of arrays once I turn on optimization. With optimization totally
off, "vectors with iterator" is half the speed as array but with
optimization on, surprisingly, "vector with iterator" takes an
insignificant lead with -O2 and array or "vector with pointers" are a
bit faster with -O3

Most of the time, the performance difference will not matter while the
safety (bugs and buffer overflow) are likely to matter most of the
time.

I agree though - I do not use new[] except in the classes that hide it
from me.
Also - technically the (2003) std does not guarantee that the memory of
std::vector is allocated contiguously, right?

Wrong, it is guaranteed.
std:string are not guaranteed contiguous yet although I have yet to
see one that isn't but vector is guaranteed.
See:
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3

Yannick
 
A

Andrey Tarasevich

Martin said:
Of course if the memory allocation functions for the POD in question be
overloaded, then it would break with high probability.
> ...
> Make it 100% sure (for VC8) when new/delete are not overloaded for
the POD.

Not necessarily "for the POD". The global memory allocation functions
can be overloaded. (You you can't overload memory allocation functions
specifically for 'char', which is what was used in your original example).

Note, that it is impossible to say whether the global functions are
overloaded by just looking at the type your are trying to work with.
For most projects I have worked with though, this can be ruled out. (I'm
sure there are some very valid examples where it's used.)

I don't understand "ruled out" here. You could say that for most
projects you have worked with the overloading didn't take place. Which
is mildly strange.

And, once again, "ruling it out" for the global overload requires the
inspection of the entire project.
Remember, new/delete, new[]/delete[] and malloc/free are three
alternative and completely independent memory allocation approaches,
which bear absolutely no relation to each other. For this reason, they
can't be mixed in the above manner.

As I see it, they are independent in the standard and it's undefined
behavior according to that.

They are independent in practice as well. You just haven't seen them
overloaded for some reason.
However, my question was (and I'm sure there are): On which
platform/compiler *implementations* will code such as this break in
release code. (break = access violation or memory leak)

Not exactly. What you checked is on which platforms this will work with
that platform's default implementations of memory
allocation/deallocation functions.

I don't see how it can be even remotely useful.
 
L

lbonafide

However, my question was (and I'm sure there are): On which
platform/compiler *implementations* will code such as this break in
release code. (break = access violation or memory leak)

How should we know and why do you expect us to test for you? God, I
hope you don't write production software for anyone.
 
E

Eberhard Schefold

Martin said:
Are you sure these don't mess up anything in VC8?

Yes, 100% sure.
Anyway this question is braindead. You use delete[]
for arrays and never free() with operator new.

This is question is quite valid. Indeed it becomes more valid with
answers such as this.

There are so many morons who are 100% sure that it's safe to pour
lighter fluid into a burning barbecue fire -- /although/ they've been
told otherwise. "Sissies", they say. They do it dozens of times, and
nothing bad happens. Then they'll do it once more and get a third-degree
burn, and some bystanders too.

I just don't get into the mindset of these people.
 
B

Bo Persson

Martin said:
Andrey said:
Remember, new/delete, new[]/delete[] and malloc/free are three
alternative and completely independent memory allocation
approaches, which bear absolutely no relation to each other. For
this reason, they can't be mixed in the above manner.

As I see it, they are independent in the standard and it's undefined
behavior according to that.
However, my question was (and I'm sure there are): On which
platform/compiler *implementations* will code such as this break in
release code. (break = access violation or memory leak)

We don't know, but your question is backwards. The fact that it works
on VC8 is just by chance, not by design.


Bo Persson
 
B

Bo Persson

Martin said:
Kai-Uwe Bux said:
Martin T. wrote:

....

It is undefined behavior on any platform. That makes it somewhat
hard to produce a test case.

Well, I am sure the standard says something about the outcome of a
delete[] for PODs ... ?
So, if the outcome of the free(new char[n]) is the same, one could
say it does not break in this specific implementation, right?

But you would have to have some explicit guarantees from the
implementor. Like Kai-Uwe says, we can never test for undefined
behavior, because it doesn't have to be consistent.


Bo Persson
 

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,176
Messages
2,570,950
Members
47,500
Latest member
ArianneJsb

Latest Threads

Top