Each
AnsiString instance (that isn't
Nil, of course) points to a null-terminated string immediately preceded by the structure defined in
rtl/inc/astrings.inc:
Type
PAnsiRec = ^TAnsiRec;
TAnsiRec = Record
CodePage : TSystemCodePage;
ElementSize : Word;
{$ifdef CPU64}
{ align fields }
Dummy : DWord;
{$endif CPU64}
Ref : SizeInt;
Len : SizeInt;
end;
Empty (zero-length) strings are represented by
Nil. This could cause problems when interacting with C code, because an empty string in C is
not represented as a null pointer, but as a
pointer to a null byte. This is why
PChar(SomeAnsiString) doesn't just extract the pointer value, but actually inserts code just for this case (essentially like this):
function AnsiStringToPChar(const Str: AnsiString): PChar;
begin
Result := Pointer(Str);
if Result = Nil then Result := #0; // FPC_EMPTYCHAR
end;
Since
AnsiString is a reference-counted type and as such needs to be
managed by the compiler, there is some overhead whenever reference-count manipulation is required. More specifically, in functions where an
AnsiString is either defined or passed in as a plain parameter (i.e. not
const, constref, var, out), an implicit
try/finally block is generated to handle the reference-count decrement at the end (unless
{$implicitexceptions} is disabled, that is).
[...] in what situations should one be concerned with manual memory management when manipulating memory through pointers?
In situations that involve
manually overwriting the pointer value:
procedure Leak(Str: AnsiString);
begin
Pointer(Str) := Nil;
end;
The above function first increments
Str's reference count due to the reasons outlined above, then
forgets about it when the pointer is overwritten, only to finally attempt to decrement the reference count of
Nil (which has no effect), leaving the original string with an inflated reference count and thus leaking it.
Edit: Fixed two errors in a whopping four lines of example code
