fpc/tests/webtbs/tw7100.pp
florian ee10850a57 * patch by Sergey Larin: Reducing and aligning the size of TAnsiRec, TUnicodeRec for CPU64, resolves #38018:
For CPU64, the size of record TAnsiRec and TUnicodeRec is 16 bytes instead of 24.
    Which is very good also because of the alignment. when allocating memory, the address
    of the first character of the string will be aligned on the 16-byte boundary.
    At the same time, the useless Dummy field, which is needed in CPU64 for exactly alignment, has been removed.
    For CPU32 (and CPU16), the record size has not changed, so procedures such as
    fpc_AnsiStr_Decr_Ref, implemented in assembler (see i386, arm), remained working correctly.
  * tests adapted
2021-10-17 11:13:29 +02:00

91 lines
2.1 KiB
ObjectPascal

{ %opt=-Sd }
{$IFNDEF FPC}
{$apptype console}
{$ENDIF}
uses SysUtils;
var
s1: string;
// To compile in Delphi
{$IFNDEF FPC}
type
pinteger = ^integer;
pbyte = ^byte;
{$ENDIF}
function GetS1: string;
begin
result := s1;
end;
function ThrowsException(a: integer): string;
begin
result := '';
if (a > 0) then
Abort;
end;
function Test(cmd: integer): integer;
begin
result := 0;
if GetS1 <> '' then
begin
try
// GetS1 returns reference to S1, and this reference is stored on a temp variable.
// It's Ok, until an exception is raised in ThrowsException.
// The problem is the compiler is planning to store the result of ThrowsException on the same temp variable.
// As the ThrowsException raises an exception, this temp variable never gets new value, and in fact remains
// equal to S1.
// So when the temp variables are cleaned on exit from function Test, the S1's ref counter falls to
// 0, and S1 is released.
ThrowsException(cmd);
result := 1;
except
result := -1;
write('(exception occured) ');
end;
end;
end;
procedure DumpString(const s: string);
var
i: sizeint;
pb: pbyte;
begin
pb := pbyte(s);
write(IntToHex(StringRefCount(s), sizeof(sizeint)*2),' ',IntToHex(Length(s), sizeof(sizeint)*2),' ');
if StringRefCount(s)<>1 then
halt(1);
if Length(s)<>2 then
halt(1);
// Printing string bytes
for i:=1 to length(s) do
begin
write(IntToHex(pb^, 2), ' ', '''', char(pb^), ''' ');
inc(pb);
end;
writeln;
end;
begin
s1 := '1'; s1 := s1 + '2'; // making a string with variable ref counter
write('Dump of S1 at start: '); DumpString(s1);
writeln;
// Calling Test(0) - normal flow, string S1 remains in correct state
writeln('Test(0) -> ', Test(0));
write('Dump of S1 after Test(0): '); DumpString(s1);
writeln;
// Callig Test(1) - exception is raised by ThrowsException function, and this causes incorrect decrement of S1's ref-counter
writeln('Test(1) -> ', Test(1));
write('Dump of S1 after Test(1): '); DumpString(s1);
writeln;
end.