[fpc-pascal] Difference between string and Tbytes as procedure arguments?

Bo Berglund bo.berglund at gmail.com
Sun Nov 5 09:55:14 CET 2023


I am maintaining an old utility program that started out about 20+ years ago
using Delphi7.

The utility communicates via RS232 with a measuring system in order to retrieve
and process recorded data and at the time this was started I used strings as
buffers for the serial comm.

A string at the time was really just an array of 1-byte characters but it had
useful functions for manipulating data inside so it made sense to use strings at
the time.

But as time evolved and Borland changed the meaning of string to now be
unicodestring it could no longer be used as a comm buffer, so I switched
declaration to AnsiString or even RawByteString to keep the existing utility
tools operational.

New programs I wrote would use TBytes as buffer instead...

Then about 6-7 years ago I had to do a major overhaul of the program in order to
improve the user interface and add support for switching languages in the UI and
at that time I also tried my best to replace the AnsiString buffers with TBytes
buffers. At this time I was on Delphi XE5.

It all looked OK until I recently got a call from a distributor who had
discovered that for a certain type of seldom used data collection mode the
output was corrupted when transfered to disk....

And now I have found that the corruption happens inside a function that analyzes
one of the data packets where it will remove the start header record from the
buffer and then continue parsing the data items. (The buffer is sent in as a
regular argument without the var specifier).

Following this analysis in main code the buffer itself (that was used in the
previous call) is saved to disk in binary format.
And here is the problem:

The saved image of the buffer lacks the header part (30 bytes)...

So my question is this:
Is there a difference in handling the arguments between string, AnsiString,
RawByteString and TBytes in a declaration like this:

function TSSConnection.ParseCmdFileData(var SSCmdFile: TSSCommandFile; Buf:
AnsiString): boolean;

and this:

function TSSConnection.ParseCmdFileData(var SSCmdFile: TSSCommandFile; Buf:
TBytes): boolean;

In the first instance it looks like the function receives a *copy* of the data
in the Buf argument and in the second case it receives a pointer to the actual
live data such that in the first case the argument source remains untouched
whereas in the second case the argument source is changed just as it had been
declared as var...

Is there a way to simply tell Delphi/FreePascal to treat also TBytes as copy
rather than a pointer to the real data?


-- 
Bo Berglund
Developer in Sweden



More information about the fpc-pascal mailing list