Results 1 to 10 of 10

Thread: Pointer points to rubbish after irrelevant operation

  1. #1
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default Pointer points to rubbish after irrelevant operation

    Simba Code:
    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?

  2. #2
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by riwu View Post
    ...

    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:

    Pascal Code:
    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.
    Last edited by Brandon; 12-19-2015 at 05:32 PM.
    I am Ggzz..
    Hackintosher

  3. #3
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default

    Quote Originally Posted by Brandon View Post
    ...
    Thanks for the explanation!
    That makes sense, so returning a pointer is pointless without also returning the data (or making it global)...

  4. #4
    Join Date
    Sep 2008
    Location
    Not here.
    Posts
    5,422
    Mentioned
    13 Post(s)
    Quoted
    242 Post(s)

    Default

    Quote Originally Posted by riwu View Post
    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.

  5. #5
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default

    Quote Originally Posted by tls View Post
    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)


    Quote Originally Posted by Brandon View Post
    Pascal Code:
    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.

  6. #6
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by riwu View Post
    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:
    Simba Code:
    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.
    Last edited by slacky; 12-20-2015 at 02:54 AM.
    !No priv. messages please

  7. #7
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    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:
    Simba Code:
    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 :)

    Quote Originally Posted by tls View Post
    Allocate memory on the heap.
    now i see what u meant...
    Last edited by riwu; 12-20-2015 at 02:47 AM.

  8. #8
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by riwu View Post
    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:
    Simba Code:
    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;
    !No priv. messages please

  9. #9
    Join Date
    Sep 2008
    Location
    Not here.
    Posts
    5,422
    Mentioned
    13 Post(s)
    Quoted
    242 Post(s)

    Default

    Quote Originally Posted by riwu View Post
    now i see what u meant...
    Ya sorry was on mobile so I couldn't share an example.

  10. #10
    Join Date
    Oct 2011
    Posts
    805
    Mentioned
    21 Post(s)
    Quoted
    152 Post(s)

    Default

    What's behind a variable name is actually a pointer to the first element of dynamic array.

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

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •