Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Lets put it another way

Reply
Thread Tools

Lets put it another way

 
 
Paul
Guest
Posts: n/a
 
      05-24-2011

"Joshua Maurice" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
On May 24, 3:00 am, Joshua Maurice <(E-Mail Removed)> 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.


*p2 does not attempt to access the deallocated memory.
*p2 yields a memory address, it accesses some object that seems to be a
pointer in most situations, but when passed to typeid or sizeof it does not
behave like a pointer.
This AFAICT from reading online seems to be the typical behaviour of a C++
array type object, therefore it seems that the pointer points to an array
type object which is created by the creation of the pointer itself and not
by the allocation.

For example consider this simple example:
int* p = new int[16];

In this dynamic array there is no array type object. It is a simple int*
that points to a block of memory.
sizeof and typeid do not work here because there is no array object.
Now consider this:

int (*p)[3] = (int (*)[3])new int[3];
Now we have an arraytype object because we can access typeinfo and sizeof.

The allocation of memory alone does not create an array type object, it is
the declaration of an object using square brackets that creates the array
type object.








 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      05-24-2011
On 05/25/11 12:58 AM, Paul wrote:
>
> "Ian Collins"<(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> On 05/24/11 09:20 PM, Paul wrote:
>>>
>>> "Ian Collins"<(E-Mail Removed)> wrote in message
>>> news:(E-Mail Removed)...
>>>> 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.


Because there isn't an address to store. The typeid operator (like
sizeof) works with types, not values. In a simple case such as this the
operand is not evaluated. Until you understand this you will be stuck
in limbo.

I could have simplified my simplification further by writing

std::cout << typeid(int[3]).name() << std::endl;

See? No memory address just a type.

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


There isn't an address. Where's the address in typeid(int).name()? Or
sizeof(int)?

--
Ian Collins
 
Reply With Quote
 
 
 
 
Paul
Guest
Posts: n/a
 
      05-24-2011

"Ian Collins" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On 05/25/11 12:58 AM, 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.

>
> Because there isn't an address to store. The typeid operator (like
> sizeof) works with types, not values. In a simple case such as this the
> operand is not evaluated. Until you understand this you will be stuck in
> limbo.
>
> I could have simplified my simplification further by writing
>
> std::cout << typeid(int[3]).name() << std::endl;
>
> See? No memory address just a type.
>


There is an address stored.

Look at the code :

int main(){
int (*pp)[3] = (int (*)[3])new int[3];
std::cout<<*pp;
}
If this does not output an address what the hell is it?


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

>
> There isn't an address. Where's the address in typeid(int).name()? Or
> sizeof(int)?
>

The address is shown in my code above.
Have you lost your brain today?

 
Reply With Quote
 
Joshua Maurice
Guest
Posts: n/a
 
      05-24-2011
On May 24, 6:54*am, "Paul" <(E-Mail Removed)> wrote:
> "Joshua Maurice" <(E-Mail Removed)> wrote in message
>
> news:(E-Mail Removed)...
> On May 24, 3:00 am, Joshua Maurice <(E-Mail Removed)> 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.
>
> *p2 does not attempt to access the deallocated memory.


Doesn't matter. It's UB. Attempting to read the pointer, not the
deallocated memory, is UB. At least it is according to the C spec, and
I expect that the C++ standard will follow suit if it hasn't already.

> For example consider this simple example:
> int* p = new int[16];
>
> In this dynamic array there is no array type object. It is a simple int*
> that points to a block of memory.
> sizeof and typeid do not work here because there is no array object.
> Now consider this:
>
> int (*p)[3] = (int (*)[3])new int[3];
> Now we have an arraytype object because we can access typeinfo and sizeof..
>
> The allocation of memory alone does not create an array type object, it is
> the declaration of an object using square brackets that creates the array
> type object.


And I still don't know what you mean by array type object vs array
object. Until you explain that technical distinction to me, you're
literally just spouting effective nonsense, as you just invented those
terms and no one else knows what you're saying.
 
Reply With Quote
 
Joshua Maurice
Guest
Posts: n/a
 
      05-24-2011
On May 24, 6:32*am, "Paul" <(E-Mail Removed)> wrote:
> "Joshua Maurice" <(E-Mail Removed)> wrote in message
> --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.


Any dereference of that pointer, basically, is UB. There's no reason
to do the cast in the first place.
 
Reply With Quote
 
Paul
Guest
Posts: n/a
 
      05-24-2011

"Joshua Maurice" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
On May 24, 6:54 am, "Paul" <(E-Mail Removed)> wrote:
> "Joshua Maurice" <(E-Mail Removed)> wrote in message
> > 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.
>
> *p2 does not attempt to access the deallocated memory.


--Doesn't matter. It's UB. Attempting to read the pointer, not the
--deallocated memory, is UB. At least it is according to the C spec, and
--I expect that the C++ standard will follow suit if it hasn't already

This pointer obviously points to something that has a value that is
displayed on the screen as a memory address. It certainly doesn't point to
the integer objects that were allocated by new, so what does it point to?
How can you say it is UB if you do not first establish what it is pointing
to?

> For example consider this simple example:
> int* p = new int[16];
>
> In this dynamic array there is no array type object. It is a simple int*
> that points to a block of memory.
> sizeof and typeid do not work here because there is no array object.
> Now consider this:
>
> int (*p)[3] = (int (*)[3])new int[3];
> Now we have an arraytype object because we can access typeinfo and sizeof.
>
> The allocation of memory alone does not create an array type object, it is
> the declaration of an object using square brackets that creates the array
> type object.


--And I still don't know what you mean by array type object vs array
--object. Until you explain that technical distinction to me, you're
--literally just spouting effective nonsense, as you just invented those
--terms and no one else knows what you're saying.

Well consider the following:

int arr[3]={0};
std::cout<< arr;

The above does not output an array object, it outputs a memory address.
To output the array object you need to loop and dereference:

for (int i=0; i<3; ++i){
std::cout<< arr[i] << std::endl;
}

The array type object is a region of memory that contains a value that is
some memory address.
The array object is a region of memory than contains three integer objects,
each with the value 0.








 
Reply With Quote
 
Paul
Guest
Posts: n/a
 
      05-24-2011

"Joshua Maurice" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
On May 24, 6:32 am, "Paul" <(E-Mail Removed)> wrote:
> "Joshua Maurice" <(E-Mail Removed)> wrote in message
> --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.


--Any dereference of that pointer, basically, is UB. There's no reason
--to do the cast in the first place.

What derefernecing any pointer in C++ is UB?
Or just pointers to array type objects?

I'm unsure what you are saying here, what do you think this pointer points
to?

 
Reply With Quote
 
Oliver Jackson
Guest
Posts: n/a
 
      05-24-2011
On May 24, 1:11*pm, "Paul" <(E-Mail Removed)> wrote:
> "Ian Collins" <(E-Mail Removed)> wrote in message
>
> news:(E-Mail Removed)...
>
>
>
>
>
> > On 05/25/11 12:58 AM, 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.

>
> > Because there isn't an address to store. *The typeid operator (like
> > sizeof) works with types, not values. *In a simple case such as this the
> > operand is not evaluated. *Until you understand this you will be stuck in
> > limbo.

>
> > I could have simplified my simplification further by writing

>
> > std::cout << typeid(int[3]).name() << std::endl;

>
> > See? *No memory address just a type.

>
> There is an address stored.
>
> Look at the code :
>
> int main(){
> *int (*pp)[3] = (int (*)[3])new int[3];
> *std::cout<<*pp;}
>
> If this does not output an address what the hell is it?
>
> >> 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?

>
> > There isn't an address. *Where's the address in typeid(int).name()? *Or
> > sizeof(int)?

>
> The address is shown in my code above.
> Have you lost your brain today?


**** yeah! Your posts ROCK!!
 
Reply With Quote
 
Joshua Maurice
Guest
Posts: n/a
 
      05-24-2011
On May 24, 3:56*pm, "Paul" <(E-Mail Removed)> wrote:
> "Joshua Maurice" <(E-Mail Removed)> wrote in message
>
> news:(E-Mail Removed)...
> On May 24, 6:54 am, "Paul" <(E-Mail Removed)> wrote:
>
> > *p2 does not attempt to access the deallocated memory.

>
> --Doesn't matter. It's UB. Attempting to read the pointer, not the
> --deallocated memory, is UB. At least it is according to the C spec, and
> --I expect that the C++ standard will follow suit if it hasn't already
>
> This pointer obviously points to something that has a value that is
> displayed on the screen as a memory address. It certainly doesn't point to
> the integer objects that were allocated by new, so what does it point to?
> How can you say it is UB if you do not first establish what it is pointing
> to?


Take the following program:
#include <stdlib.h>
#include <stdio.h>
int main()
{ char* a = (char*)malloc(1);
char* b = a;
free(a);
printf("%p\n", b);
}
This program has UB in C, and as I said will likely have UB in C++, or
it already is UB in C++. See the defect report for more details:

http://www.open-std.org/jtc1/sc22/wg...ocs/dr_260.htm

> --And I still don't know what you mean by array type object vs array
> --object. Until you explain that technical distinction to me, you're
> --literally just spouting effective nonsense, as you just invented those
> --terms and no one else knows what you're saying.
>
> Well consider the following:
>
> int arr[3]={0};
> std::cout<< arr;
>
> The above does not output an array object, it outputs a memory address.
> To output the array object you need to loop and dereference:
>
> for (int i=0; i<3; ++i){
> std::cout<< arr[i] << std::endl;
>
> }
>
> The array type object is a region of memory that contains a value that is
> some memory address.
> The array object is a region of memory than contains three integer objects,
> each with the value 0.


I suggest you take a course in compilers, or read a book, like one of
the Dragon Books, Red or Green. You have gross misunderstandings of
both the C++ object model, and how compilers actually generate code.
There is no such thing as an "array-type object", as you've defined
it. In these examples, there are only array objects and pointer
objects - including pointers to arrays and pointers to individual
elements, not "array-type objects".

Consider:
void foo()
{ int x[3];
int* y = x;
cout << y;
}

"x" is a piece of text. It is a preprocessor token. It is an
identifier for an auto (stack) variable. It names an object. It names
an (array) object of type "int [3]". That array object has three sub-
objects of type "int".

"y" is a piece of text. It is a preprocessor token. It is an
identifier for an auto (stack) variable. It names an object. It names
a (pointer) object of type "int*". It holds the address of the first
element of the auto (stack) array x.

This function "uses" the following objects:
- the array object x, and its 3 unnamed int sub-objects,
- the pointer object y,
- the object cout.
There is no "array-type object".

There is no such thing as the array-type object. A common compiler
(and one which has sizeof(int) == 4) will implement this function by:
- allocating the stack space,
- taking the stack pointer and adding 0 to get the address of the
first element of the array object x,
- taking the stack pointer and adding 12 to get the address of the
pointer object y,
- storing the address of the first element of the array object x into
the object y, (we previously obtained both addressed - see above), (or
it'll put it into a register, or both, depending on the particulars
and how the compiler wants to use registers),
- set up the state required to call "std:perator<<" according to the
calling-convention, which includes putting the value of the pointer
object y in memory a certain offset from the stack pointer register
value, or in a particular register,
- calling a jump instruction or some such to call function
"std:perator<<",
- reading the return value of that function from a calling-convention
location, such as a particular register or from memory at a particular
offset from the stack pointer register value,
- and so on.

Consider the function:
void foo()
{ int* x = new int[3];
cout << x;
}

"x" is a piece of text. It is a preprocessor token. It is an
identifier for an auto (stack) variable. It names an object. It names
a (pointer) object of type "int*". It holds a value of the address of
the first element of the unnamed dynamically allocated array.

This function "uses" the following objects:
- the pointer object x,
- the object cout,
- the unnamed, dynamically allocated, array object.
- the 3 unnamed int sub-objects of the unnamed, dynamically allocated,
array object.
There is no "array-type object".

A common compiler will implement this function by:
- allocating the stack space,
- taking the stack pointer and adding 0 to get the address of the
pointer object x,
- set up the state required to call the new operator according to the
calling-convention, which includes putting the value 3 in memory a
certain offset from the stack pointer register value, or in a
particular register,
- reading the return value of that function from a calling-convention
location, such as a particular register or from memory at a particular
offset from the stack pointer register value,
- storing the return result of the function call, aka "new int[3]",
aka a pointer to the first element of the dynamically allocated array,
into the pointer object x, (we previously obtained its addressed - see
above), (or it'll put it into a register, or both, depending on the
particulars and how the compiler wants to use registers),
- and then it will call "std:perator<<" just like it in the earlier
example,
- and so on.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      05-25-2011
On 05/25/11 08:11 AM, Paul wrote:
> "Ian Collins"<(E-Mail Removed)> wrote:
>> On 05/25/11 12:58 AM, Paul wrote:
>>>>
>>> You are not addressing the what stores the memory address.

>>
>> Because there isn't an address to store. The typeid operator (like
>> sizeof) works with types, not values. In a simple case such as this the
>> operand is not evaluated. Until you understand this you will be stuck in
>> limbo.
>>
>> I could have simplified my simplification further by writing
>>
>> std::cout<< typeid(int[3]).name()<< std::endl;
>>
>> See? No memory address just a type.
>>

>
> There is an address stored.
>
> Look at the code :
>
> int main(){
> int (*pp)[3] = (int (*)[3])new int[3];
> std::cout<<*pp;
> }
> If this does not output an address what the hell is it?


The value returned by new.

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

>>
>> There isn't an address. Where's the address in typeid(int).name()? Or
>> sizeof(int)?
>>

> The address is shown in my code above.


The address in your code id the value return by new. No amount of
casting will change that.

> Have you lost your brain today?


Oh how mature you are.

--
Ian Collins
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
why does the following with Queue, q.put('\x02', True) not put itin the queue? Gabriel Rossetti Python 3 04-25-2008 03:41 PM
OT: Lets all get high James MCSE 93 10-19-2005 05:45 PM
Review: Lets get a T@2 Part 1 Silverstrand Reviews & How-To's 0 06-20-2005 02:34 AM
Another way to put labels on page than asp:label tshad ASP .Net 2 04-08-2005 12:00 AM
is there a hardware / driver combination out there the lets win2k connect to the network before login?? christiane kewitz Wireless Networking 1 02-13-2005 01:08 AM



Advertisments