Re: Lets put it another way
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-c9b197253f8b@p13g2000yqh.googlegroups.com...
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 t=
o
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 pointin=
g
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/wg14/www/docs/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 object=
s,
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::operator<<" 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::operator<<",
- 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::operator<<" just like it in the earlier
example,
- and so on.