On May 24, 3:56*pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Joshua Maurice" <joshuamaur...@gmail.com> wrote in message
>
> news:b6334244-434f-4c62-954b-...
> On May 24, 6:54 am, "Paul" <pchris...@yahoo.co.uk> 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.