Reputation: 101
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
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