user11935527
user11935527

Reputation: 101

Incorrect behaviour of a for loop

I have encountered some incorrect behaviour in a procedure to write a UT8String to a stream (Delphi 10.3). The procedure is very straightforward and reads:

procedure StreamWriteUTF8String(Stream: TStream; Value: UTF8String);
  {Writes a UTF8 character string to a  Stream}
var
  n, i: longword;
begin
  n:= Length(Value);
  StreamWriteCardinal(Stream, n);
  for i:= 0 to n-1 do
    Stream.WriteBuffer(Value[i+1], SizeOf(UTF8Char));
end;

When an empty Value string is passed to the procedure, so that n, the string length, is zero, the bounds of the for loop control variable i should be 0 to -1. Therefore in this case the statement Stream.WriteBuffer inside the for loop should not be executed. This is because the termination test, i<= UpperBound, which should be executed before the loop body, should evaluate to False. It is my understanding that a for loop should be implemented in such a way that the body should be executed zero or more times depending on the bounds of the control variable tested before proceeding to the body.

However I am finding that in the case of n=0 the compiled code does not skip the statement Stream.WriteBuffer as one would expect, with the result that the Value[i+1] gives rise to an access violation exception.

Let me say that I have similar procedures for writing other types of string to a stream, most of which can handle a zero length string without any problem.

Can anyone suggest why in this case the loop does not appear to be working as it ought?

Upvotes: 1

Views: 193

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 109168

You have declared n as a LongWord, which is an unsigned integer of 32 bits.

Therefore, n - 1 will wrap around and be 4294967295.

You should use the Integer type instead, for both i and n. That's a 32-bit signed integer, so n - 1 will indeed be -1.

Upvotes: 11

Related Questions