Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Lets put it another way (http://www.velocityreviews.com/forums/t748865-lets-put-it-another-way.html)

Paul 05-24-2011 01:14 AM

Lets put it another way
 
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;
std::cout<< typeid(*p2).name();
}


In the last 2 lines does an array type object exist, even though there is no
array object?

If not what is the object that stores the address and is interpreted as an
array type by the typeid expression?



Ian Collins 05-24-2011 01:33 AM

Re: Lets put it another way
 
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;


UB yet again.

> std::cout<< typeid(*p2).name();
> }
>
>
> In the last 2 lines does an array type object exist, even though there is no
> array object?


No.

> If not what is the object that stores the address and is interpreted as an
> array type by the typeid expression?


The typeid and sizeof operators do not evaluate their expression (unless
in case of typeid the type is polymorphic). So no object is required.

--
Ian Collins

Joshua Maurice 05-24-2011 01:39 AM

Re: Lets put it another way
 
On May 23, 6:33*pm, Ian Collins <ian-n...@hotmail.com> wrote:
> 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;

>
> UB yet again.


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.

Paul 05-24-2011 09:20 AM

Re: Lets put it another way
 

"Ian Collins" <ian-news@hotmail.com> wrote in message
news:940g82Ft2pU20@mid.individual.net...
> 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;

>
> UB yet again.
>
>> std::cout<< typeid(*p2).name();
>> }
>>
>>
>> In the last 2 lines does an array type object exist, even though there is
>> no
>> array object?

>
> No.
>
>> If not what is the object that stores the address and is interpreted as
>> an
>> array type by the typeid expression?

>
> The typeid and sizeof operators do not evaluate their expression (unless
> in case of typeid the type is polymorphic). So no object is required.
>

You do not seem to understand the question.
I said ..if not what is the object that stores the address?
So what is this object? Do you know?



Paul 05-24-2011 09:42 AM

Re: Lets put it another way
 

"Joshua Maurice" <joshuamaurice@gmail.com> wrote in message
news:eb724d42-4a22-44aa-91ab-1a58972eabb6@e17g2000prj.googlegroups.com...
On May 23, 6:33 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> 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;

>
> UB yet again.


--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.
The objects that need to be deleted are integer objects. and they get
deleted in this case.
If you think it is necessary to cast to int* prior to calling delete then
assume that and then can you answer the question about the object that
contains the memory address, or do you not know?





Joshua Maurice 05-24-2011 10:00 AM

Re: Lets put it another way
 
On May 24, 2:42*am, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Joshua Maurice" <joshuamaur...@gmail.com> wrote in message
>
> news:eb724d42-4a22-44aa-91ab-1a58972eabb6@e17g2000prj.googlegroups.com...
> On May 23, 6:33 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>
> > 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;

>
> > UB yet again.

>
> --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.

> 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[].

> 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.

> 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.

#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]",
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),
3- calls delete[] on a pointer of the wrong type and thus invokes UB,
4- and finally, the program again invokes UB by attempting to read the
result of a null pointer dereference.

Joshua Maurice 05-24-2011 10:03 AM

Re: Lets put it another way
 
On May 24, 3:00*am, Joshua Maurice <joshuamaur...@gmail.com> wrote:
> 4- and finally, the program again invokes UB by attempting to read the
> result of a null pointer dereference.


Err, sorry, not null pointer dereference. My apologies. It's an
indeterminate value. This is clearer in the C standard where they
cleared this up recently AFAIK. As soon as a pointer to a dynamically
allocated piece of memory has been passed to a deallocation function,
all copies of that pointer value, and moreover all pointer values in
the entire program that point into that region of memory, become
indeterminant. Any read of an indeterminant value is UB.

Ian Collins 05-24-2011 10:27 AM

Re: Lets put it another way
 
On 05/24/11 09:20 PM, Paul wrote:
>
> "Ian Collins"<ian-news@hotmail.com> wrote in message
> news:940g82Ft2pU20@mid.individual.net...
>> 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;

>>
>> UB yet again.
>>
>>> std::cout<< typeid(*p2).name();
>>> }
>>>
>>>
>>> In the last 2 lines does an array type object exist, even though there is
>>> no
>>> array object?

>>
>> No.
>>
>>> If not what is the object that stores the address and is interpreted as
>>> an
>>> array type by the typeid expression?

>>
>> The typeid and sizeof operators do not evaluate their expression (unless
>> in case of typeid the type is polymorphic). So no object is required.
>>

> You do not seem to understand the question.


You do not appear to understand the answer.

> I said ..if not what is the object that stores the address?
> So what is this object? Do you know?


There isn't an object. The compiler knows the type of *p2. You may as
well have written

#include <iostream>
#include <typeinfo>

typedef int (*pparr)[3];

int main(){
pparr p2;
std::cout << typeid(*p2).name() << std::endl;
}


--
Ian Collins

Paul 05-24-2011 12:58 PM

Re: Lets put it another way
 

"Ian Collins" <ian-news@hotmail.com> wrote in message
news:941ffpFt2pU22@mid.individual.net...
> On 05/24/11 09:20 PM, Paul wrote:
>>
>> "Ian Collins"<ian-news@hotmail.com> wrote in message
>> news:940g82Ft2pU20@mid.individual.net...
>>> 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;
>>>
>>> UB yet again.
>>>
>>>> std::cout<< typeid(*p2).name();
>>>> }
>>>>
>>>>
>>>> In the last 2 lines does an array type object exist, even though there
>>>> is
>>>> no
>>>> array object?
>>>
>>> No.
>>>
>>>> If not what is the object that stores the address and is interpreted as
>>>> an
>>>> array type by the typeid expression?
>>>
>>> The typeid and sizeof operators do not evaluate their expression (unless
>>> in case of typeid the type is polymorphic). So no object is required.
>>>

>> You do not seem to understand the question.

>
> You do not appear to understand the answer.
>
>> I said ..if not what is the object that stores the address?
>> So what is this object? Do you know?

>
> There isn't an object. The compiler knows the type of *p2. You may as
> well have written
>
> #include <iostream>
> #include <typeinfo>
>
> typedef int (*pparr)[3];
>
> int main(){
> pparr p2;
> std::cout << typeid(*p2).name() << std::endl;
> }
>
>

You are not addressing the what stores the memory address.
A memory address value is stored so there must be an object to store this
value, you say there is no object so what is it that stores this value?


Paul 05-24-2011 01:32 PM

Re: Lets put it another way
 

"Joshua Maurice" <joshuamaurice@gmail.com> wrote in message
news:f830366e-f74d-4d92-9259-2b6faed3d6ee@q12g2000prb.googlegroups.com...
On May 24, 2:42 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> > 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;

>
> > UB yet again.

>
> --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.



All times are GMT. The time now is 08:40 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.