PDA

View Full Version : Pointer points to rubbish after irrelevant operation



riwu
12-19-2015, 04:44 PM
function f(): pointer;
var
arr: array[0..0] of integer;
begin
arr[0]:= 123;
result := @arr //mention tag activated with ';', lol
end;

var
p: Pointer;
x: array of String;
begin
p:= f();
writeln(Integer(p^)); //prints 123
SetLength(x, 5); //some irrelevant array operation
writeln(Integer(p^)); //prints rubbish !!!
end.


Behaviour is same in FPC.

Also is there a way to use pointers for dynamic arrays?

Brandon; any idea?

Brandon
12-19-2015, 05:06 PM
...


Undefined behaviour. P is pointing to a locally defined array. You cannot store a pointer to stack allocated variables. The lifetime of the variable is local. It is destroyed when the function exits/returns. The variable must exist on the heap (allocated via new, setlength, etc). Your variable array is stack allocated array[0..0] of Integer;

It prints the first time because the memory was not used or overwritten and the OS/program hasn't cleaned up yet. However, after doing the writeln it either stores new information in that memory OR it wipes it clean and thus you access a non-existent array.


Pascal:
https://ideone.com/2WyTtc


C/C++ (actually crashes):
https://ideone.com/uLbxBs



Allocate the array:


function f(): pointer;
var
arr: array of integer;
begin
SetLength(arr, 1); //heap allocated array
arr[0]:= 123;
exit(@arr[0]); //Pointer to first element.
end;


var
p: Pointer;
x: array of String;
begin
p:= f();
writeln(Integer(p^)); //prints 123
SetLength(x, 5); //some irrelevant array operation
writeln(Integer(p^)); //prints rubbish !!!
end.


Either that or return the array. Pretty sure in pascal when you return a dynamic array (set length array), it returns a reference/pointer to it and increases the reference count. If you return a local array, it returns a COPY of the entire array instead.

In other words, returning a pointer to an array is the same as just returning the array but only if its a dynamic array. You can see the effect if you run the function on a thread and access it from two different threads (changing the first index on the main thread and printing it on the second thread). The second thread sees the change because its the same array.

riwu
12-20-2015, 12:15 AM
...
Thanks for the explanation!
That makes sense, so returning a pointer is pointless without also returning the data (or making it global)...

tls
12-20-2015, 12:55 AM
Thanks for the explanation!
That makes sense, so returning a pointer is pointless without also returning the data (or making it global)...

Allocate memory on the heap.

riwu
12-20-2015, 01:02 AM
Allocate memory on the heap.
The data at the address of the heap might still be replaced after the array variable goes out of scope? (since having a pointer to it does not seem to constitute a proper reference requiring the program to continue reserving that memory for the variable)
So you'd have to allocate it globally? (eg. global var)





function f(): pointer;
var
arr: array of integer;
begin
SetLength(arr, 1); //heap allocated array
arr[0]:= 123;
exit(@arr[0]); //Pointer to first element.
end;


var
p: Pointer;
x: array of String;
begin
p:= f();
writeln(Integer(p^)); //prints 123
SetLength(x, 5); //some irrelevant array operation
writeln(Integer(p^)); //prints rubbish !!!
end.


Either that or return the array.
This example does not work for me btw.

slacky
12-20-2015, 02:33 AM
The data at the address of the heap might still be replaced after the array variable goes out of scope? (since having a pointer to it does not seem to constitute a proper reference requiring the program to continue reserving that memory for the variable)
So you'd have to allocate it globally? (eg. global var)

You can't alloc dynamic arrays locally, they will get cleaned up by Lape/FPC once you exit the function or once ref-count is 0, depending on what happens first.

You can however allocate your own data on the heap:

type PInt32 = ^Int32;

function AllocThingy(): PInt32;
begin
ReallocMem(Result, SizeOf(Int32)*2);
MemMove([123,999][0], Result^, SizeOf(Int32)*2);
end;

var
p: Pointer;
x: Array of String;
begin
p := AllocThingy();
SetLength(x, 5); //some irrelevant array operation

WriteLn(PInt32(p)^); //prints 123
WriteLn(PInt32(p+4)^); //prints 999
FreeMem(p); //you have to free it yourself now..
end.

riwu
12-20-2015, 02:44 AM
You can't alloc dynamic arrays locally, they will get cleaned up by Lape/FPC once you exit the function or once ref-count is 0, depending on what happens first.

You can however allocate your own data on the heap:

type PInt32 = ^Int32;

function AllocThingy(): PInt32;
begin
ReallocMem(Result, SizeOf(Int32)*2);
MemMove([123,999][0], Result^, SizeOf(Int32)*2);
end;

var
p: Pointer;
x: Array of String;
begin
p := AllocThingy();
SetLength(x, 5); //some irrelevant array operation

WriteLn(PInt32(p)^); //prints 123
WriteLn(PInt32(p+4)^); //prints 999
FreeMem(p); //you have to free it yourself now..
end.

Thanks, good to know how to manually allocate memory for data :)


Allocate memory on the heap.
now i see what u meant...

slacky
12-20-2015, 02:53 AM
Thanks, good to know how to manually allocate memory for data :)


now i see what u meant...
for FPC it would be something alĂ  this:

type PInt32 = ^Int32;

function AllocThingy(): PInt32;
var arr:Array [0..1] of Int32 = (123,999);
begin
Result := GetMem(SizeOf(Int32) * Length(arr));
Move(arr[0], Result^, SizeOf(Int32) * Length(arr));
end;

procedure Test();
var
p: PInt32;
begin
p := AllocThingy();

WriteLn((p+0)^); //prints 123
WriteLn((p+1)^); //prints 999

FreeMem(p); //you have to free it yourself now..
end;

tls
12-20-2015, 05:59 PM
now i see what u meant...

Ya sorry was on mobile so I couldn't share an example.

bg5
12-27-2015, 04:15 PM
What's behind a variable name is actually a pointer to the first element of dynamic array.

program new;
var TPA :TPointArray;
begin
SetLength(TPA,10);
writeln(IntToHex(integer(TPA)));
writeln(@TPA[0]);
end.