Pointer to String casts

This post describes how to avoid a recent mistake I’ve seen in a Delphi application related to “Pointer to String” casting. Consider the following example:

  PSomeStrData: Pointer;
  SomeStr: String;
  { Allocate 128 bytes of memory }
  PSomeStrData := GetMemory(128);

  { Fills in the memory pointed with a C-style string }
  FillWithACStyleStr(PSomeStrData, 128);
  SomeStr := String(PSomeStrData);

In this example an untyped pointer was allocated with 128 bytes of memory, then filled with some C-style string (FillWithACStyleStr doesn’t exist, I just used it as an example here). After that, a pointer-to-string cast was performed, and finally the resulted string was printed to the console. This code is wrong! The assignment: “SomeStr := String(PSomeStrData);” will be converted by the compiler to a _UStrAsg (in System.pas) which receives 2 parameters (SomeStr and PSomeStrData) of type UnicodeString. This means that PSomeStrData is treated as an UnicodeString rather than the expected char*! This will probably result in some access violation because the memory _before_ PSomeStrData must contain the standard StrRec structure each string has.

The most simple solution to this hypothetical bug is to use PChar instead of Pointer for PSomeStrDatavariable. This ensures that the compiler will emit the correct call to _UStrFromPWChar which copies the data over to SomeStr.