Recent

Author Topic: [SOLVED] Why Move(); needs pointers dereferenced?  (Read 7337 times)

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
[SOLVED] Why Move(); needs pointers dereferenced?
« on: August 26, 2014, 11:28:51 am »
Can someone explain me why Move(const Src; var Dest; Length); needs the pointers dereferenced?
I expected Move(pSrc, pDest, 16); but it doesn't work. See the code. When I type pSrc^, it's the value on that address, isn't it? But it works.

Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var pSrc, pHelp, pDest: Pointer;
    i: Integer;
begin
  GetMem(pSrc, 16);
  GetMem(pDest, 16);
  for i:=0 to 15 do
    PByte(pSrc+i)^:=i;
  for i:=0 to 15 do
    writeln(PByte(pDest+i)^);
  pHelp:=pDest;
  Move(pSrc^, pHelp^, 16);  //HERE
  for i:=0 to 15 do
    writeln(PByte(pDest+i)^);
  FreeMem(pSrc, 16);
  FreeMem(pDest, 16);
end;

Thanks.
« Last Edit: August 26, 2014, 12:20:01 pm by Blaazen »
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

howardpc

  • Hero Member
  • *****
  • Posts: 3181
Re: Why Move(); needs pointers dereferenced?
« Reply #1 on: August 26, 2014, 11:36:53 am »
Because you don't want Move to copy the value of the pointers in your program (some arbitrary location determined by the OS), but to copy the contents of the memory they point to.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8112
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Why Move(); needs pointers dereferenced?
« Reply #2 on: August 26, 2014, 11:46:56 am »
You need to understand how untyped parameters work. They're passed by reference, but inside the routine, they're still treated as a normal value. Which means, you don't care about its address, but its value. So you set the first value to move/be moved, not the pointer to it.

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Why Move(); needs pointers dereferenced?
« Reply #3 on: August 26, 2014, 11:48:45 am »
Quote
Because you don't want Move to copy the value of the pointers in your program (some arbitrary location determined by the OS), but to copy the contents of the memory they point to.
Yes, I agree. But when I type pSrc^ and Dest^, it is the value on that address, not the address itself, so how can the procedure Move(); know where is the source and destination?
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Why Move(); needs pointers dereferenced?
« Reply #4 on: August 26, 2014, 11:54:28 am »
BTW, this works too:
Code: [Select]
Move(PByte(pSrc)^, PByte(pHelp)^, 16);
Quote
You need to understand how untyped parameters work. They're passed by reference, but inside the routine, they're still treated as a normal value. Which means, you don't care about its address, but its value. So you set the first value to move/be moved, not the pointer to it.
Then I don't understand well.
I got variable: Pointer. It's somewhere in memory.
Its value is address, it points to another memory, where I got my 16 bytes.
Once I do PByte(pSrc)^ I got value of the very first byte (of that 16B) and the information about the original address is lost, isn't it?
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7506
Re: Why Move(); needs pointers dereferenced?
« Reply #5 on: August 26, 2014, 12:15:40 pm »
Then I don't understand well.
I got variable: Pointer. It's somewhere in memory.
Its value is address, it points to another memory, where I got my 16 bytes.
Once I do PByte(pSrc)^ I got value of the very first byte (of that 16B) and the information about the original address is lost, isn't it?

The parameter construct if move (without type) is called a  "formal parameter".  The compiler passes the address of what is given as parameter to the move procedure, IOW it is a by-reference construct. This means that the address of the expression is passed (the address where the pointer value is stored) and not the value (the contents of the variable is passed on)

The base principle is not too different from a VAR parameter (by reference) and without (by value). The main difference is that formal parameters take any type for which an address can be calculated.   Even an untyped pointer only takes any pointer expression by value.
« Last Edit: August 26, 2014, 12:17:20 pm by marcov »

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: Why Move(); needs pointers dereferenced?
« Reply #6 on: August 26, 2014, 12:19:30 pm »
Thanks. That makes sense.

EDIT: I marked it as [SOLVED] but feel free to continue discussion.

EDIT2: Now I see, it's the same what Leledumbo tried to tell me.
« Last Edit: August 26, 2014, 12:27:24 pm by Blaazen »
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

BrunoK

  • Full Member
  • ***
  • Posts: 190
  • Retired programmer
Re: [SOLVED] Why Move(); needs pointers dereferenced?
« Reply #7 on: August 26, 2014, 01:07:23 pm »
D:\fpc-laz\fpc-2.6.4\rtl\inc\systemh.inc
Procedure Move(const source;var dest;count:SizeInt);

For (const source;var dest) the compiler extracts the addresses of source and dest (it does something like @SomeSource and @SomeDest) then passes them on the stack (or thru registers) to the move procedure. That procedure expects pointers to the effective memory being moved and its target. When specified as pSrc^, pHelp^  ( @pSrc^, @pHelp^ are passed ) it says to the compiler where source and dest are located in the heap (getmem memory space) and that is those addresses that are source and dest in heap allocated memory.

Move(pSrc, pDest, 16); would push the address of the pSrc and pDest (@pSrc and @pDest) local variables to the stack for the move procedure and that would cause a copy of 16 bytes of Button1Click(Sender: TObject); >>>LOCAL VAR's (stack) <<< on, more or less themselves, thus destroying the local stack and quite likely crash the application because it would copy to the stack RETURN address or maybe destroy the pointers to pass to FreeMem.

I don't know if my comments add anything to the discussion, but what I can tell you is that when I haven't used pointers for a week or 2, I HAVE TO 'LEARN' THEM AGAIN, and that has been going on for the last 16 years with Delphi or FPC. Pointers are regular C programmer stuff, but once the pascal way is well understood it is comparatively clearer.
Lazarus trunk r. 62137/27.10.2019 (+/- patches regarding TScrollBar, IntitalSetupDialog, Options.Environment options, SearchResults).  Lazarus 3.0.6 raw from svn.
FPC 3.0.4 32 bits. (+heaptrc with leaked ClassName+Revisited TList) , Windows 10 Pro x64 (v. 1903 / 18362.418)

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: [SOLVED] Why Move(); needs pointers dereferenced?
« Reply #8 on: August 26, 2014, 01:36:42 pm »
Thanks for further explanation.

Quote
Move(pSrc, pDest, 16); would push the address of the pSrc and pDest (@pSrc and @pDest) local variables to the stack for the move procedure and that would cause a copy of 16 bytes of Button1Click(Sender: TObject); >>>LOCAL VAR's (stack) <<< on, more or less themselves, thus destroying the local stack and quite likely crash the application because it would copy to the stack RETURN address or maybe destroy the pointers to pass to FreeMem.

Exactly what happened here to me.  :)
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Basile B.

  • Guest
Re: [SOLVED] Why Move(); needs pointers dereferenced?
« Reply #9 on: August 28, 2014, 04:49:30 am »
In the same fashion, I always asked myself why the heck , still in Move(), the parameter dest is before src   :o
compat with c memmove ? because of the inline asm ?

Leledumbo

  • Hero Member
  • *****
  • Posts: 8112
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: [SOLVED] Why Move(); needs pointers dereferenced?
« Reply #10 on: August 28, 2014, 06:20:28 am »
In the same fashion, I always asked myself why the heck , still in Move(), the parameter dest is before src   :o
compat with c memmove ? because of the inline asm ?
Ask the original author. But I believe it exists since TP days, which is written by Anders, and do you what he's specialized in, at least in his early TP days? x86 assembly. And what do you think this convention reflect? That's right, x86 mnemonic ;)

hinst

  • Sr. Member
  • ****
  • Posts: 303
Re: [SOLVED] Why Move(); needs pointers dereferenced?
« Reply #11 on: August 28, 2014, 11:08:03 am »
In the same fashion, I always asked myself why the heck , still in Move(), the parameter dest is before src   :o
compat with c memmove ? because of the inline asm ?
why? it is not:
Code: [Select]
Procedure Move(const source;var dest;count:SizeInt);source comes first

I believe that in some functions destination comes first to mimic assignment:
Code: [Select]
Move(a, b);
// like
a := b
Too late to escape fate

Blaazen

  • Hero Member
  • *****
  • Posts: 2782
  • POKE 54296,15
    • Eye-Candy Controls
Re: [SOLVED] Why Move(); needs pointers dereferenced?
« Reply #12 on: August 28, 2014, 12:56:19 pm »
Yes, hinst is right.
In FPC it is Move(src, dest, size);
while original C version have
memcpy(dest, src, size);
Lazarus 2.1.0 r61214:62238 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/