delete[] p or delete[] *p

P

Paul

Leigh Johnston said:
Think about how you draw a family tree: ancestors toward the top;
descendants toward the bottom (the tree is upside down).

A family tree is exact opposite of a class inheritance, a parent object is
the most derived object.
In a family tree the children are most derived.
Anyway it doesn't matter how it *seems* to you; what is important is to be
technically accurate and to use correct terminology: casting from derived
to base is called "upcasting"; casting from base to derived is called
"downcasting".
Yes says the proven idiot who thinks p doesn't point to an array with:
int* p = new int[5]
 
G

Goran

What I dont understand is what exactly your argument is, you fail to
communicate properly.
You said something was UB but no expalanation, just because it appearedto
be UB to you.
Now you are blabbing on about some assert thing. WHat exactly has all this
got to do with delete[] ?

Your cast is on the new side invokes UB. By consequence, your examples
are buggy, and so is your call to operator[].
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Why?
Please explain why it is UB?

Because you are casting from a pointer of one type to a pointer of an
unrelated type (and that's what the compiler told you, too, when you
tried without a cast, now did it?)
You do not seem to accept that cast invokes UB, so I made you a piece
of code that shows why your cast is, and should be, UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your code doesn't prove the cast is UB.

It does. See below.
For that piece of code, I used assert to ascertain what should be true
(that "0" equals "b.i"). If you compile this snippet without NDEBUG,
"assert(0 == b.i)" should not fire, because, clearly, Base() sets i to
0. And yet, this assert does fire (on common implementations). Why?
Because your cast invoked UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Eh? Because you code asserts something to be not equal you assert this to
mean the cast produces UB? How do you come to that conclusion?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

That something is b.i, which is initialized to 0 and never changed.
Yet, assert does fire.

My claim is that it fires because cast was UB, and, on common
implementations, result is that code sees that b.i equals one, not
zero.

My claim is that implementation is correct in everything it has done,
that code is correct in every detail, except for the UB cast. If cast
wasn't UB, assert(0 == b.i) would not fire. Since it does, it's
because cast is UB.

Goran.
 
K

Kai-Uwe Bux

Paul said:
Kai-Uwe Bux said:
Paul said:
Paul wrote:


int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
int (*p3)[5] = new int[5][5]; /*2d array*/
delete[] p1;
delete[] p2;
delete[] p3;

What is the difference with the above deletes?

As far as I am concerned, difference is: first two are UB (platform-
specific at best), because of wrong casts in corresponding "new",
whereas the third one is correct.

Why are they UB? After having a read through the rellevant pages of
the standard I don't think that it is UB.

We shall see.

The standard specifically states that the pointer returned from new
must
be castable.

Correct: [5.2.10/7] states:

A pointer to an object can be explicitly converted to a pointer to an
object of different type.65) Except that converting an rvalue of type
"pointer to T1" to the type "pointer to T2" (where T1 and T2 are
object types and where the alignment requirements of T2 are no
stricter than those of T1) and back to its original type yields the
original pointer value, the result of such a pointer conversion is
unspecified.

That implies that after casting, you have an unspecified result. The
only
thing you can do with it, is casting back, and even that presupposes
compatible alignment requirement.

But I didn't cast to a different object type, I casted to an array of
objects of the same type.
That quote is talking about converting between objects of a different
types.
[...]

Ok, so you are saying that the C-style cast you are using is _not_
governed
by clause [5.2.10/7]. Please specify which clause of the standard you are
relying on in determining the behavior of the cast expression.
I was saying the cast wasn't an issue with me, I don't see things in such
a way that every cast produces UB.

Not _every_ cast. Just the one in your code :)
A cast from int* to int*[] doesn't seem like a major conversion of any
major concern to me.

It is a conversion not governed by anything else than [5.2.10/7]. And the
governing clause [5.2.10/7] specifies that the result of the cast is
unspecified. Using those unspecified values farther down the road in any way
not listed in [5.2.10/7] is undefined behavior as per:

1.3.12 undefined behavior
behavior, such as might arise upon use of an erroneous program construct
or erroneous data, for which this International Standard imposes no
requirements. Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition of
behavior.


Best,

Kai-Uwe Bux
 
K

Kai-Uwe Bux

Paul said:
Kai-Uwe Bux said:
Here is a data point:

#include <iostream>

class BaseA{
public:
int k;
BaseA() {std::cout<<"Constructing base a\n";}
virtual ~BaseA(){std::cout<<"Destructing base a\n";}
};

class BaseB {
public:
int i;
BaseB() {std::cout<<"Constructing base b\n";}
virtual ~BaseB(){std::cout<<"Destructing base b\n";}
};

class Derived: public BaseA, BaseB {
public:
int j;
Derived() {std::cout<<"Constructing derived\n";}
~Derived(){std::cout<<"Destructing derived\n";}
};

int main() {
Derived (*p1) [3] = new Derived [2][3];
BaseB (*p2)[3] = (BaseB (*)[3])p1;
delete [] p2;
}

This program segfaults on my machine.

I think, it is allowed to do so.
Ok I had a quick look at this.
This works perfectly ok on my machine. So are you are saying is that its
UB to cast a pointer to Derived into a pointer to BaseB?

I don't say that.
Or are you saying that its only UB to cast a pointer of Derived (*)[size]
to BaseB (*)[size], but its ok to cast a Derived* to a baseB*?

I don't even say that. What I say is that casting the pointer p1 (of type
Derived(*)[3]) to the type (BaseB(*)[3]) results in an unspecified value of
p2. What is UB is calling delete[] on the unspecified value p2.
As far as I was aware is perfectly ok to downcast to a Base class. As long
as the Base class has a virtual destructor the object destruction will
destruct the whole Dervied object.

True. If we had

Derived* p1 = new Derived;
BaseB* p2 = (BaseB*)p1;
delete p2;

everything would be perfectly fine. Note, however, that the case is
_entirely_ different, starting with the C-style cast (BaseB*)p1 being a
static_cast<> as opposed to the reinterpret_cast<> from the previous
snippet. Now, the (redundant) cast is governed by [5.2.9/2]. The delete
expression is governed by [5.3.5/3].

Note, however, that this snippet has UB:

Derived* p1 = new Derived [3];
BaseB* p2 = (BaseB*)p1; // fine so far, but p2[1] would be UB
delete [] p2; // UB as per [5.3.5/3]

This involves the distinction of dynamic and static types: p2 has dynamic
type Derived* and static type BaseB*.


Best,

Kai-Uwe Bux
 
P

Paul

Kai-Uwe Bux said:
int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
int (*p3)[5] = new int[5][5]; /*2d array*/
delete[] p1;
delete[] p2;
delete[] p3;

What is the difference with the above deletes?

As far as I am concerned, difference is: first two are UB (platform-
specific at best), because of wrong casts in corresponding "new",
whereas the third one is correct.

Why are they UB? After having a read through the rellevant pages of
the standard I don't think that it is UB.

We shall see.

The standard specifically states that the pointer returned from new
must
be castable.

Correct: [5.2.10/7] states:

A pointer to an object can be explicitly converted to a pointer to an
object of different type.65) Except that converting an rvalue of type
"pointer to T1" to the type "pointer to T2" (where T1 and T2 are
object types and where the alignment requirements of T2 are no
stricter than those of T1) and back to its original type yields the
original pointer value, the result of such a pointer conversion is
unspecified.

That implies that after casting, you have an unspecified result. The
only
thing you can do with it, is casting back, and even that presupposes
compatible alignment requirement.

But I didn't cast to a different object type, I casted to an array of
objects of the same type.
That quote is talking about converting between objects of a different
types.
[...]

Ok, so you are saying that the C-style cast you are using is _not_
governed
by clause [5.2.10/7]. Please specify which clause of the standard you
are
relying on in determining the behavior of the cast expression.
I was saying the cast wasn't an issue with me, I don't see things in such
a way that every cast produces UB.

Not _every_ cast. Just the one in your code :)
Oh right so its a case of any time I do a cast its UB because you say so.
Like I bother what people like you think if thats the case.
 
P

Paul

Kai-Uwe Bux said:
Paul said:
Kai-Uwe Bux said:
Here is a data point:

#include <iostream>

class BaseA{
public:
int k;
BaseA() {std::cout<<"Constructing base a\n";}
virtual ~BaseA(){std::cout<<"Destructing base a\n";}
};

class BaseB {
public:
int i;
BaseB() {std::cout<<"Constructing base b\n";}
virtual ~BaseB(){std::cout<<"Destructing base b\n";}
};

class Derived: public BaseA, BaseB {
public:
int j;
Derived() {std::cout<<"Constructing derived\n";}
~Derived(){std::cout<<"Destructing derived\n";}
};

int main() {
Derived (*p1) [3] = new Derived [2][3];
BaseB (*p2)[3] = (BaseB (*)[3])p1;
delete [] p2;
}

This program segfaults on my machine.

I think, it is allowed to do so.
Ok I had a quick look at this.
This works perfectly ok on my machine. So are you are saying is that its
UB to cast a pointer to Derived into a pointer to BaseB?

I don't say that.
Or are you saying that its only UB to cast a pointer of Derived (*)[size]
to BaseB (*)[size], but its ok to cast a Derived* to a baseB*?

I don't even say that. What I say is that casting the pointer p1 (of type
Derived(*)[3]) to the type (BaseB(*)[3]) results in an unspecified value
of
p2. What is UB is calling delete[] on the unspecified value p2.
I thought you might actually have a valid point, but now its quite clear
your just another idiot who has no other objective than to prove anything I
say is wrong.
I don't really care what people like you think tbh 99% of the time you don't
have a clue what you're talking about.
 
P

Paul

What I dont understand is what exactly your argument is, you fail to
communicate properly.
You said something was UB but no expalanation, just because it appeared
to
be UB to you.
Now you are blabbing on about some assert thing. WHat exactly has all
this
got to do with delete[] ?

Your cast is on the new side invokes UB. By consequence, your examples
are buggy, and so is your call to operator[].
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Why?
Please explain why it is UB?

Because you are casting from a pointer of one type to a pointer of an
unrelated type (and that's what the compiler told you, too, when you
tried without a cast, now did it?)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No my code compiles fine, The types are not unrelated they are both int
types.
I can cast from int[] to int* implicitly because its a realated type.
 
P

Paul

Leigh Johnston said:
A family tree is exact opposite of a class inheritance, a parent object
is the most derived object.
In a family tree the children are most derived.

A family tree was an example of a tree which you typically draw upside
down (the root is at the top); an inheritance hierarchy is typically
viewed as a tree where the base classes are at the root of the tree and
similar to a family tree the root is at the top hence the term "upcast".
Anyway it doesn't matter how it *seems* to you; what is important is
to be technically accurate and to use correct terminology: casting
from derived to base is called "upcasting"; casting from base to
derived is called "downcasting".
Yes says the proven idiot who thinks p doesn't point to an array with:
int* p = new int[5]

p is not a pointer to an array; p is a pointer to an int.
No p points to the initial element *of an array*, by definiton it points to
an array.
You are the one who continually provides evidence to everyone reading your
posts as to who the idiot actually is; you certainly have yet to provide
any evidence or proof that those who continually correct you are idiots
although giving a troll such as yourself any time probably *is* idiotic.

If you are not a troll and you actually believe the bullshit you post then
your cause is a hopeless one.
Very good but it's obvious to anyone, with isn't an idiot, that you are an
idiot. As for the idiots who agree with you, I don't really care what they
think .
:)
 
P

Paul

Leigh Johnston said:
On 31/03/2011 00:42, Paul wrote:
[...]
Anyway it doesn't matter how it *seems* to you; what is important is
to be technically accurate and to use correct terminology: casting
from derived to base is called "upcasting"; casting from base to
derived is called "downcasting".

Yes says the proven idiot who thinks p doesn't point to an array with:
int* p = new int[5]

p is not a pointer to an array; p is a pointer to an int.
No p points to the initial element *of an array*, by definiton it points
to an array.

Whilst p does point to the initial element of an array that does not mean
that p is a pointer to an array; p is a pointer to an int.
If p points to the intial element *OF AN ARRAY*, then by defintion it points
to an array.
Were you born stupid or did you grow into it?
 
G

Goran

Because you are casting from a pointer of one type to a pointer of an
unrelated type (and that's what the compiler told you, too, when you
tried without a cast, now did it?)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No my code compiles fine

Irrelevant. There's gigabytes of source that compile fine, but does
not work.
, The types are not unrelated they are both int
types.
I can cast from int[] to int* implicitly because its a realated type.

You can, but that is irrelevant for what you're trying to do. Besides,
cast is already implicit, so why would you!?

The problem is elsewhere: when you do "new TYPE[size1][size2]", the
type of result is "TYPE**", and that is __unrelated__ to "TYPE (*)
[size2]". Ppeople already have quoted you relevant portions of the
standard, and I even went through the hassle of showing you, in great
detail, __why__ what you are trying to do can't work well. In the
process of doing so, I offered you, effectively, a __proof__ that your
cast is UB (this type of proof is commonly called "proof by
contradiction", and I can rephrase my proof more formally if you
wish).

You should take note of this, I believe: by your own words: "I can
cast from int[] to int* __implicitly__ (emphasis mine) because its a
realated type". However, no implementation allowed you to assign
result of new TYPE[size1][size2] to TYPE(*)[size2]. There is __no__
implicit conversion there (and with a good reason, too, see above). So
you resorted to a cast. An UB one.

Goran.
 
G

Goran

Yes says the proven idiot who thinks p doesn't point to an array with:
int* p = new int[5]
p is not a pointer to an array; p is a pointer to an int.
No p points to the initial element *of an array*, by definiton it points
to an array.

I don't know what definition you are talking about, but either the
definition, or your interpretation thereof, is wrong.

Return type of expression "new TYPE[5]" is "TYPE*", not e.g. TYPE[5],
or, I dunno, TYPE(*)[5]. Array (as in TYPE[size]) is in no way
involved there. Arrays and pointers mix in some other contexts^^^.

It looks like the syntax (new TYPE[5]), that resembles an array
declaration, confuses you. You might want to think of it this way:

int* p = new int(1); // p is a pointer to int.
p = new int[2];
// p is __still__ a pointer to int
int i;
p = &i;
// p is __still__ a pointer to int
int a[3];
p = a; // ^^^ implicit array-to-pointer conversion
// p is __still__ a pointer to int

You seem to believe that there is something as pointer-to-array
conversion (or pointer-to-pointertoarray conversion). That belief is
wrong.

Goran.
 
P

Paul

Yes says the proven idiot who thinks p doesn't point to an array
with:
int* p = new int[5]
p is not a pointer to an array; p is a pointer to an int.
No p points to the initial element *of an array*, by definiton it
points
to an array.

I don't know what definition you are talking about, but either the
definition, or your interpretation thereof, is wrong.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The definition in the C++ standard says it points to the first element OF AN
ARRAY.
therefore by definition it points to an array you idiot.


<snip >
 
G

Goran

The definition in the C++ standard says it points to the first element OFAN
ARRAY.
therefore by definition it points to an array you idiot.

First part, I agree. Second part (the "therefore" one), is false (and
is not in the standard, either).

Here, a practical example why __your__ "therefore" is wrong:

class A
{
public:
A() : i(0) {}
const int i;
};

class B : public A
{
public:
B() : j(1) {}
const int j;
};

int main(int, char*[])
{
const B b[2];
const A* a = b;
if (a->i == 0)
std::cout << "a points to the array b" << std::endl;
a++;
std::cout << "I did a++; now it points to the second element of the
array b;" << std::endl;
std::cout << "That's what pointers do, right?" << std::endl;
if (a->i == 1)
{
std::cout << "Hmmm... no object of type A has i that equals 1." <<
std::endl;
std::cout << "I must have invoked UB somewhere. I wonder where..."
<< std::endl;
std::cout << "Perhaps in the part where I said that a points to
the array b?" << std::endl;
std::cout << "Nooo... Un-possible!";
}
return 0;
}

Goran.
 
S

SG

[...]
The problem is elsewhere: when you do "new TYPE[size1][size2]",
the type of result is "TYPE**",

No, it is not. The type of this new expression is TYPE(*)[size2]
(assuming TYPE is not an array-type).

[...]
The definition in the C++ standard says it points to the first element
OF AN ARRAY. therefore by definition it points to an array [...]

Wow. Apparently, the discussion is still about the banana vs bunch of
bananas thing. I still see no definition of the word "pointer" or the
expression "points to X" in the C++ ISO standard that would justify
your use of the words "therefore by definition" in this context.
Consider the possibility that you are (perhaps unintentionally)
augmenting the standard's text with your personal understanding of
what "points to X" means exactly.

Regardless of the interpretation of "points to X", an array is not a
pointer. Since you evaded revisiting this claim of yours in favour of
this stupid discussion about the semantics of "points to X", my
conclusion is you are too proud to admit that you were wrong about the
"an array is just a pointer" issue.

SG
 
G

Goran

[...]
The problem is elsewhere: when you do "new TYPE[size1][size2]",
the type of result is "TYPE**",

No, it is not. The type of this new expression is TYPE(*)[size2]
(assuming TYPE is not an array-type).

Whoops, indeed. Heat of the discussion ;-) ...

Goran.
 
P

Paul

The definition in the C++ standard says it points to the first element OF
AN
ARRAY.
therefore by definition it points to an array you idiot.

First part, I agree. Second part (the "therefore" one), is false (and
is not in the standard, either).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

It IS the defintioon in the standard, the standard states it points to the
first element OF AN ARRAY, therefore it cannot NOT point to an array.

The standard certainly doesn't state, that it doesn't point to an array, as
you are saying.
You do not accept the opinion of experts who say that a T* can point to a T,
or an array of T's.


<snip>
 
P

Paul

Leigh Johnston said:
Leigh Johnston said:
On 31/03/2011 00:42, Paul wrote:
[...]
Anyway it doesn't matter how it *seems* to you; what is important is
to be technically accurate and to use correct terminology: casting
from derived to base is called "upcasting"; casting from base to
derived is called "downcasting".

Yes says the proven idiot who thinks p doesn't point to an array
with:
int* p = new int[5]

p is not a pointer to an array; p is a pointer to an int.
No p points to the initial element *of an array*, by definiton it
points
to an array.

Whilst p does point to the initial element of an array that does not
mean that p is a pointer to an array; p is a pointer to an int.
If p points to the intial element *OF AN ARRAY*, then by defintion it
points to an array.

By whose definition? Yours?
By the defintion of the C++ standards, that state the pointer points to the
first element OF AN ARRAY.
It can't not point to an array if it points to the first element OF AN
ARRAY, you idiot.
 
P

Paul

SG said:
[...]
The problem is elsewhere: when you do "new TYPE[size1][size2]",
the type of result is "TYPE**",

No, it is not. The type of this new expression is TYPE(*)[size2]
(assuming TYPE is not an array-type).

[...]
The definition in the C++ standard says it points to the first element
OF AN ARRAY. therefore by definition it points to an array [...]

Wow. Apparently, the discussion is still about the banana vs bunch of
bananas thing. I still see no definition of the word "pointer" or the
expression "points to X" in the C++ ISO standard that would justify
your use of the words "therefore by definition" in this context.
Consider the possibility that you are (perhaps unintentionally)
augmenting the standard's text with your personal understanding of
what "points to X" means exactly.
No I agree the majority of experts who also say a pointer of type T* can
point to a T , or an array of T's.
Its the people here who are saying that T* does not point to an array who
are making an idiotic and nonsensical statement that goes against the common
understanding. The burden of proof lies with them/YOU.

Regardless of the interpretation of "points to X", an array is not a
pointer. Since you evaded revisiting this claim of yours in favour of
this stupid discussion about the semantics of "points to X", my
conclusion is you are too proud to admit that you were wrong about the
"an array is just a pointer" issue.
This is absolute bollocks , I never said an array was the same as a pointer,
I say that in some situations it is, for all intensive purposes, the same.
Now you say you know more about my views than I do? Go to France you fin
idiot.
 
P

Paul

Leigh Johnston said:
Leigh Johnston said:
On 31/03/2011 02:22, Paul wrote:

On 31/03/2011 00:42, Paul wrote:
[...]
Anyway it doesn't matter how it *seems* to you; what is
important is
to be technically accurate and to use correct terminology: casting
from derived to base is called "upcasting"; casting from base to
derived is called "downcasting".

Yes says the proven idiot who thinks p doesn't point to an array
with:
int* p = new int[5]

p is not a pointer to an array; p is a pointer to an int.
No p points to the initial element *of an array*, by definiton it
points
to an array.

Whilst p does point to the initial element of an array that does not
mean that p is a pointer to an array; p is a pointer to an int.

If p points to the intial element *OF AN ARRAY*, then by defintion it
points to an array.

By whose definition? Yours?
By the defintion of the C++ standards, that state the pointer points to
the first element OF AN ARRAY.
It can't not point to an array if it points to the first element OF AN
ARRAY, you idiot.

You are just going round in circles. Again: there is a difference between
the not so technical term "points to" and the technical term "a pointer
to".

A *pointer to an int* is *a pointer to an int* not *a pointer to an
array*; pretty simple IMO so I wonder why you don't "get" it.
And a pointer to an array of int is a pointer to an array.
This is a pointer to an array , not a pointer to a single int, pretty
simple:
int* p = new int[6];

You obviously have an overwhelming desire to get your own back after the
many times i have proved you wrong. I have won this argument arleady and I
see no need to reply to your idiotic nonsense anymore.
 

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
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top