Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi strings and reference counting

Delphi uses reference counting with strings.

Do this mean that there is only one memory allocation for '1234567890' and all a,b,c,d, e and f.s reference to it?

 type  
   TFoo = class
    s: string;
   end;

  const 
    a = '1234567890';
    b = a;
    c : string = a;

  var
    d: string;
    e: string;
    f: TFoo;

  function GetStr1(const s: string): string;
  begin
   Result := s;
  end;

  function GetStr2(s: string): string;
  begin
   Result := s;
  end;

  begin
   d := GetStr1(b);
   e := GetStr2(c);
   f := TFoo.Create;
   f.s := a;
  end;
like image 302
pKarelian Avatar asked Feb 13 '10 06:02

pKarelian


3 Answers

Yes, there's only one allocation in your specific example. If you had used UniqueString, as mghie says, or if you had built the string dynamically, then you end up with a new string allocation even if the string contents are the same as some other string.

However, an interesting fact about your specific example: there is actually no memory "allocated" for the string '1234567890' at all. The data for string constants is stored in the executable image on disk, and is paged in by the OS when the code accesses it. It takes up memory address space, as part of the entire executable module's in-memory mapping, but since it is backed by the original executable on disk, it doesn't form part of the process's committed memory and won't need backing in the page file.

For example, this program will report an access violation on run:

{$apptype console}
uses SysUtils;

const
  s = '1234567890';
procedure Change(const r: string);
var
  p: PChar;
begin
  p := PChar(r);
  p^ := 'x';
end;

begin
  try
    Change(s);
  except
    on e: Exception do
      Writeln(e.Message);
  end;
end.
like image 155
Barry Kelly Avatar answered Nov 07 '22 12:11

Barry Kelly


Small addition to the answer by jxac:

A copy will also be created when UniqueString() is called in code, when a character in the string is accessed by [], and when the string is typecasted to PChar. This happens even when the PChar and the string element will only ever be read.

It's important to know how to force a unique string from a potentially shared one, because there are Windows API functions that must not be called with a read-only char pointer, which a PChar to a string constant is. In that case the constant needs to be copied to a variable first, so casting it will return a PChar pointing to writable memory.

like image 23
mghie Avatar answered Nov 07 '22 11:11

mghie


yep, the strings are ref counted, a copy is created only when the contents are modified through a variable (copy on write semantics), more info here:

http://www.codexterity.com/delphistrings.htm

like image 5
user262976 Avatar answered Nov 07 '22 11:11

user262976