SRL Archive - Lape

exception with string len / tfilestream


bonsai

2014-08-21 05:55:28

I bumped into a case where I get exceptions from TFileStream.readBuffer() depending on how I set the length of the string I'm using for the buffer.

If I use a local integer or longint for setLength() all goes well.

If I use TFileStream.getSize() in the setLength() it ends up with an access violation when you call readBuffer. There are some oddities with this case:

Other operations on the string seem to work ok in this scenario. You can assign a string to it, print it, but don't call readBuffer().

HOWEVER, if you use s[1] directly in between the setLength() and the readBuffer(), now it works!

Example:

Manually create file test.txt with test data in folder that script is saved in.


program filestreamerror;

const
fmCreate = $FFFF;
fmOpenRead = 0;
fmOpenWrite = 1;
fmOpenReadWrite = 2;

procedure thisWorks();
var
testFile : TFileStream;
s: string;
i: integer;
li: longint;
begin
testFile.init(scriptPath+'test.txt', fmOpenRead);
i := testFile.getSize(); // longint -> integer
setLength(s, i); // works ok
testFile.readbuffer(s[1], testFile.getSize());
writeln(length(s), ' ', s);
testFile.free();

testFile.init(scriptPath+'test.txt', fmOpenRead);
li := testFile.getSize();
setLength(s, li); // longint -> setLength() works ok too
testFile.readbuffer(s[1], testFile.getSize());
writeln(length(s), ' ', s);
testFile.free();
end;

procedure thisDoesntWork();
var
testFile : TFileStream;
s: string;
begin
try
testFile.init(scriptPath+'test.txt', fmOpenRead);

// using result of getSize() causes problems
setLength(s, testFile.getSize());

// if you uncomment this the function starts working!!
// writeln(s[1]);

testFile.readbuffer(s[1], testFile.getSize());
writeln(length(s), ' ', s);
finally
testFile.free();
end;
end;

var
ans: integer;

begin
ans := messagebox('Would you like an exception?', 'Choose', 4 {yn box});
if (ans = 6 {yes}) then
begin
writeln('You asked for it');
thisDoesntWork();
end
else
begin
thisWorks();
end;
end.

superuser

2014-08-21 09:00:46

Use

setLength(s, testFile.getSize() + 1);

and problem solved.

WriteLn(testFile.getSize()); // 10
writeln(length(s)); // 11

nielsie95

2014-08-21 10:50:41

Not sure what could be causing this, but it seems to work in the latest Simba build.