As you noted, that code is not allocating memory correctly. GetMem() operates on bytes, but s.Length is expressed in characters, not bytes, and SizeOf(Char) is 2 bytes in D2009+, so you need to double the allocation, otherwise you will have a buffer overflow on StrPCopy(), corrupting surrounding memory, which can lead to all kinds of problems, including leaks of other things that were allocated dynamically, if you corrupt the pointers to them:
var
pc: PChar;
s: String;
begin
s := 'Hello, world!';
GetMem(pc, (s.Length + 1) * SizeOf(Char));
try
StrPCopy(pc, s);
finally
FreeMem(pc);
end;
end;
Alternatively, use StrAlloc() instead:
var
pc: PChar;
s: String;
begin
s := 'Hello, world!';
pc := StrAlloc(s.Length + 1);
try
StrPCopy(pc, s);
finally
StrDispose(pc);
end;
end;
In either case, I would not use GetMem() or StrAlloc() at all, I would use a dynamic array instead:
Var
pc: array of Char; // or TArray<Char>
s: String;
begin
s := 'Hello, world!';
SetLength(pc, s.Length + 1);
StrPCopy(PChar(pc), s);
end;
Now, with that said, you claim you are seeing "leaks" when you use StrPCopy(pc, s + s) and StrPCopy(pc, s + s + s + s +s). Well, those are both buffer overflows, since you are allocating only enough memory for 1 string. It is likely that one of the pointers you are corrupting may be the one used by 'pc' or 's' itself! You will have to use the debugger to verify that. Check the values of the pointers before and after calling StrPCopy(), and see if they changed. Or even put Data Breakpoints on the pointers and see if the breakpoints are getting triggered.