Recent

Author Topic: TMemoryStream read error  (Read 2231 times)

yanes19

  • New Member
  • *
  • Posts: 36
TMemoryStream read error
« on: April 21, 2019, 01:58:01 pm »
Hi all ,
I was fighting for 3 days to manage to read some data from a memory stream (TMemoryStream) ,
with no luck

Here's the problem :
I have a String grid that contains some data about ELF object files infos and sections , it's all ok until I tried to use the TStringGrid method "SaveToStream(TMemoryStream)"
I tried every method that can read from that stream from "Read" to "ReadAnsiString; )
 to make a string stream and read from the TMemory one but none of this worked for me it always compile good but raises "Stream Read Error "

Code: Pascal  [Select][+][-]
  1.   var stringstrm : TStringStream;
  2.   var Buffer : Array of byte ;
  3.   var i :integer ;
  4.   var strTable :string ;
  5. begin
  6.   GridStream := TMemoryStream.Create;
  7.   StringGrid_Sections.SaveToStream(GridStream);
  8.   //GridStream.Position:=0;  //When this is uncommented RunError 203 is raised instead
  9.   strTable := GridStream.ReadAnsiString;
  10.  
  11.  
  12.   ShowMessage(strTable);
  13.   ShowMessage(GridStream.ReadAnsiString);
  14.  
  15. end;    

Can you guys  point out the problem ?
thanks in advance
Regards

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: TMemoryStream read error
« Reply #1 on: April 21, 2019, 02:07:26 pm »
203 is a Heap overflow..

I would say that could be a memory issue?

Are you running shy on memory ?
The only true wisdom is knowing you know nothing

yanes19

  • New Member
  • *
  • Posts: 36
Re: TMemoryStream read error
« Reply #2 on: April 21, 2019, 02:31:54 pm »
No, coding machine is an i7  , 8Gb ram , running Ubuntu 18.04 x64
With usual system config

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: TMemoryStream read error
« Reply #3 on: April 21, 2019, 02:38:14 pm »
What happens if you use:
Code: [Select]
GridStream.Seek(0, soBeginning);instead of:
Code: [Select]
GridStream.Position := 0;???

Also, after the SaveToStream(GridStream) add:
Code: [Select]
ShowMessage(IntToString(GridStream.Size));to check that the stream is not empty.

Finally, I don't know how TStringGrid.SaveToStream stores the data but ReadAnsiString expects a particular format (the length first, followed by the characters).

Oh, BTW, if all you're doing is pass it to a string, why not use a TStringStream directly?
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: TMemoryStream read error
« Reply #4 on: April 21, 2019, 02:58:36 pm »
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Var
  3. GridStream:TmemoryStream;
  4.  S:String;
  5.  X:Integer;
  6. begin
  7.  GridStream := Tmemorystream.Create;
  8.  StringGrid1.SaveToStream(GridStream);
  9.  X := GridStream.Position;
  10.  GridStream.Position := 0;
  11.  GridStream.Write(X,4);
  12.  StringGrid1.SaveToStream(GridStream);
  13.  GridStream.Position := 0;
  14. S :=  GridStream.ReadAnsiString;
  15.  GridStream.Free;
  16. end;                            
  17.  
  18.  

it needs a leading 4 byte size in the buffer from what I can read...
strange it can't figure this out but then again, maybe it's good because you can put multiples of strings in it.
The only true wisdom is knowing you know nothing

yanes19

  • New Member
  • *
  • Posts: 36
Re: TMemoryStream read error
« Reply #5 on: April 21, 2019, 03:32:15 pm »
@ Lucamar :
Thanks for replying ,
Code: Pascal  [Select][+][-]
  1. GridStream.Seek(0, soBeginning);
instead of:
Code: Pascal  [Select][+][-]
  1. GridStream.Position := 0;

make the same error (RunError 203).

Code: Pascal  [Select][+][-]
  1. ShowMessage(IntToString(GridStream.Size));
Actually , this line was there ,
I just removed it before posting the code , and it works fine and returns the correct size .

@Jamie :
Thank you really for answering
the code you suggested compiles and run as it should be but the string inside "var S " is empty even when sure the stream contains text data .
(btw if this is the issue , I wonder how TMemoryStream.GridStream.ReadAnsiString() doesnt do that for us ,
hence the name is "ReadAnsiString" , they are supposed to know exactly what they are reading )

Again ,Thank you all for replying

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: TMemoryStream read error
« Reply #6 on: April 21, 2019, 03:34:53 pm »
jamie, one thing: you should declare:
Code: Pascal  [Select][+][-]
  1. X: Int32;
to be absolutely sure it's 4 bytes on any platform. Or if it depends on the bitness, 32 vs. 64, leave it as is but do:
Code: Pascal  [Select][+][-]
  1.  GridStream.Write(X,SizeOf(X));

BTW, where did you read about that? The source?

ETA

(btw if this is the issue , I wonder how TMemoryStream.GridStream.ReadAnsiString() doesnt do that for us ,
hence the name is "ReadAnsiString" , they are supposed to know exactly what they are reading )

They know what they are reading: a string of characters. What they can't know is how long that string is (remember: a stream can have more than one type of data in it) so WriteAnsiString writes the lenght first and ReadAnsiString expects to find it there.

That's why I suggested using a TStringStream: it's like a memory stream but the data is contained in a string that can be read and written without more ado.
« Last Edit: April 21, 2019, 03:42:01 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

yanes19

  • New Member
  • *
  • Posts: 36
Re: TMemoryStream read error
« Reply #7 on: April 21, 2019, 03:56:19 pm »
I wish it's possible , this is why :
Quote
unit1.pas(344,31) Error: Incompatible types: got "TStringStream" expected "TMemoryStream"

wp

  • Hero Member
  • *****
  • Posts: 11915
Re: TMemoryStream read error
« Reply #8 on: April 21, 2019, 04:02:04 pm »
What is "StringGrid_Sections"? A TStringGrid? Is it property initialized and populated? A frequent error made is that users are not aware that column and row indexes are zero-based, i.e. after the grid's RowCount and ColCount have been set you cannot write to Cells[ColCount, RowCount], only to Cells[ColCount-1, RowCount-1]. Normally this raises an exception, but I don't know what else you are doing.

It would be best if you could extract the related code into a compilable demo which you can upload here for us to have a closer look (pack *.pas, *.lfm, *.lpi and *.lpr files as well as required data files into a common zip which you can upload under "Attachment and other options").

The attached demo writes a StringGrid to a memorystream and reads it back, byte by byte to display a simple hex dump, or as one block (by StringGrid.LoadFromStream) to display the stream content in a memo. Both pieces of information show that the stream contain xml data and consist of several lines of strings. Reading into a single string by Stream.ReadAnsiString would work in principle, but as already noted the first four bytes must contain the length of the string. In this case of an xml file, the first four bytes are the characters '<', '?', x', 'm' - taking their numeric value and combining them to a 4-byte number results in the length of approximately 1.8 GB. Of course, this is nonsense. Stuffing this into Stream.ReadAnsiString crashes a 32-bit program with the heap overflow error 203 because I do non have that memory for 32bit, and a 64-bit program crashes with a "stream read error" because reading encounters the end of the stream before all 1.8 billions of characters could be read.
« Last Edit: April 21, 2019, 11:58:17 pm by wp »

yanes19

  • New Member
  • *
  • Posts: 36
Re: TMemoryStream read error
« Reply #9 on: April 21, 2019, 04:09:27 pm »
Ok , this is is entire project
it's an open source utility and a git repo was planned to be created soon

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: TMemoryStream read error
« Reply #10 on: April 21, 2019, 11:12:25 pm »
when I did it I put the grid in edit mode and populated it a little then ran that code.

I ran debug on it and it showed content so I didn't go any further
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018