On 05/24/11 01:14 PM, Paul wrote:
Ok in connection to my previous post, lets remove the null pointer
issue
and
consider this:
#include<iostream>
typedef int (*pparr)[3];
int main(){
pparr p1 = (pparr)new int[3];
pparr p2= p1;
delete[] p1;
std::cout<< *p2<<std::endl;
--Actually, he has UB even earlier. He has UB at the delete[]. The type
--of the expression "new int[3]" is "int*". The type of the expression
--passed to delete[] to free that object must be the same type, "int*".
--It's not, and thus UB.
I raised this question about delete or delete[] on 28/03/2011 and you
didn't
know the answer then.
--I'm pretty sure I knew, and I suspect that you're willfully lying.
No I'm not lying. In response to my question about how to delete such an
object you wrote:
"I'd like to point out that AFAIK the first cast may result in a loss
of information. You're only guaranteed round-way trips through void*,
char*, and unsigned char*, (and an integer type of sufficient size).
Thus the delete[] could be UB on a conforming platform. That's right,
right?"
Ref: Posting on "delete or delete[]" on 28/3/2011
The objects that need to be deleted are integer objects. and they get
deleted in this case.
--No. An array object is the thing that was allocated, and it is an
--array object that needs to be passed to delete[].
No three integer objects were allocated and three integers must be
deallocated.
It is not one object that is allocated is it three, as this code shows:
#include <iostream>
class Foo{
public:
Foo(){std::cout<<"Constructing Foo\n";}
~Foo(){std::cout<<"Destructing Foo\n";}
};
typedef Foo (*arr_ptr)[3];
int main(){
arr_ptr foop = (arr_ptr)new Foo[3];
delete[] (Foo*)foop; /*cast back to keep you happy
*/
}
If you think it is necessary to cast to int* prior to calling delete then
assume that
--It's not what I think. It's what the standard says.
The deletion of the dynamically allocated array was not really relevant but
if you must argue about this then cast it back as I did in my code above.
and then can you answer the question about the object that
contains the memory address, or do you not know?
--Your original question in the OP post about "array type objects" vs
--"array objects" makes no sense because you invented the terms, and no
--one else knows what they mean.
My question is about the object that stores the memory address we get when
we dereference p2.
--#include<iostream>
--typedef int (*pparr)[3];
--int main(){
-- pparr p1 = (pparr)new int[3];
-- pparr p2= p1;
-- delete[] p1;
-- std::cout<< *p2<<std::endl;
--}
--This program
--1- dynamically allocates an array object, specifically "int [3]",
I don't see it as allocating one single object , I see it as allocating and
array of 3 int objects.
--2- does some funky incorrect casting invoking platform specific
--behavior (we're not guaranteed that a "int (*)[3]" pointer can round-
--trip store a "int *" pointer),
In what way is this pointer casting incorrect?
I would be very surprised if this cast was incorrect as it is a usefull way
of converting a dynamic array into a reference type, for example:
class Foo{
public:
Foo(){std::cout<<"Constructing Foo\n";}
~Foo(){std::cout<<"Destructing Foo\n";}
int x;
};
void Bar( Foo (&arg)[3]){
std::cout<<"In Bar\n";
arg[0].x= 1;
arg[1].x= 2;
arg[2].x= 3;
}
typedef Foo (*arr_ptr)[3];
int main(){
arr_ptr foop = (arr_ptr)new Foo[3];
Bar(*foop);
std::cout<< (*foop)[2].x;
}
--3- calls delete[] on a pointer of the wrong type and thus invokes UB,
That is easily corrected by casting back , this is not a point important to
the question.
--4- and finally, the program again invokes UB by attempting to read the
--result of a null pointer dereference.
There is no null pointers here.