Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using string pointer to send a string through windows messages

I am trying to understand how are pointers to strings working. I have a code (not exactly original), which was written by somebody, and the person is not around here anymore, so I need to understand the idea of such usage.

var
  STR: string;
  pStr: ^string;
begin
  STR := 'Hello world';
  New(pStr);
  pStr^ := STR;

  PostMessage(Handle, WM_USER+1, wParam(pStr), 0);
end;

Now I know for sure, that a message handler gets the message and the pointer contains the string, which can be worked with, but what happens 'under the hood' of those operations ?

I tried to make a small project. I thought, that assigning string to what a str pointer is pointing to would actually increase refcount of the original string and not make any copies of a string, but refcount remained 1 and it seems it did copy the contents.

So get the question, what happened? Calling New on a pointer allocates an empty string, right? After assignment I tried to look at refcount/length of a string the pointer pointed to like this PChar(@pStr^[1])[-8] but it returned nonsense (14), and the length byte was also wrong.

Additionally the questioin is, is it safe using pointers in such a way to pass on the string through windows messaging?

like image 498
user1651105 Avatar asked Oct 22 '13 07:10

user1651105


1 Answers

New(pStr) allocates a string on the heap and returns a pointer to it. Because string is a managed type, the string is default initialized, to the empty string. Since a string is implemented as a pointer, what you fundamentally have is a pointer to a pointer.

You code is perfectly fine, so long as you only post the message to your own process. Since the payload of the message is a pointer, it only means something in the context of the virtual address space of your process. If you wanted to send to a different process you'd need an IPC mechanism.

Clearly in the code that pulls the message off the queue you need to dispose of the string. Something like this:

var
  p: ^string;
  str: string;
....
p := Pointer(wParam);
str := p^; 
Dispose(p);

Your code to query the reference count and the length is just wrong. Here's how to do it correctly:

{$APPTYPE CONSOLE}

var
  pStr: ^string;
  p: PInteger;

begin
  New(pStr);
  pStr^ := 'Hello world';

  p := PInteger(pStr^);
  dec(p);
  Writeln(p^); // length
  dec(p);
  Writeln(p^); // ref count

  Readln;
end.

Output:

11
1
like image 179
David Heffernan Avatar answered Sep 19 '22 02:09

David Heffernan