I wrote a function for reading null-terminated strings from a TStream.strlen ? It is in system, so defaults. (As are more C like PChar handling routines)
- I want to make sure it isn't just incidental that the bug isn't surfacing in Trunk
- Am I actually doing something wrong?
- What's the correct way to read a null terminated string from a TStream in 2.0.6 then?
I wrote a function for reading null-terminated strings from a TStream.strlen ? It is in system, so defaults. (As are more C like PChar handling routines)
Also note #0 can be embedded in any true Pascal type string.
This is not a bug in any way.
if B = 0 then Exit(Result);
might produce unexpected results. Simply doing: if B = 0 then Exit;
should be enough.
Note also that in your code this line:Code: [Select]if B = 0 then Exit(Result);
might produce unexpected results. Simply doing:
triggers a range check error
Accessing Result.Section[ 0]: OK
Name=Note Table
Size=144
SectType=3
Org=-1
Bank=0
Align=1
S.Read(Data,144): OK (read: 144)
NumPatches=0
Accessing Result.Section[ 1]: OK
Name=Wave stuff
Size=0
SectType=3
Org=-1
Bank=0
Align=1
S.Read(Data,0): OK (read: 0)
NumPatches=0
Accessing Result.Section[ 2]: OK
Name=main
Size=1626
SectType=3
Org=336
Bank=0
Align=1
S.Read(Data,1626): OK (read: 1626)
NumPatches=212
Patches not supported
I wrote a function for reading null-terminated strings from a TStream.
function ReadNullTerm(S: TStream): String; var B: Byte; label bleh; begin Result := ''; bleh: B := S.ReadByte; if B = 0 then Exit(Result); Result += Char(B); goto bleh end;
Inexplicably, at a certain point in the program when using this function, there's a SIGSEGV in fpc_ansistr_decr_ref.
I can call the function successfully some amount of times, and then it breaks later; pretty weird.
This happens in Lazarus 2.0.6. I tried with a later version from Trunk, and it seems like this bug is fixed, but:
- I want to make sure it isn't just incidental that the bug isn't surfacing in Trunk
- Am I actually doing something wrong?
- What's the correct way to read a null terminated string from a TStream in 2.0.6 then?
I included the full program so you can easily reproduce the issue.
According to the example, the main mistake of the topic's author is trying to combine incompatible things. Read (or write) at a time an entry containing of managed types. This is absurd. Managed types are pointers to memory. Reading and writing them to the stream is pointless. Therefore, for data whose length is unknown, you can only use sequential byte-by-byte reads, and not the entire structure at a time. It is clear that in this case, the packed declaration for records is meaningless.
Need to change the algorithm. Read and write record fields by one of the stream, byte-by-byte, or built-in TStream functions that have already been mentioned, such as ReadString, ReadDWord, etc.
Well, The TStream.readansistring relies on what I explained, Sven. Look at its implementation. (Be a bit kind, I test this...and it is not nonsense)
Note also that in your code this line:Code: [Select]if B = 0 then Exit(Result);
might produce unexpected results. Simply doing:Code: [Select]if B = 0 then Exit;
should be enough.
According to the example, the main mistake of the topic's author is trying to combine incompatible things. Read (or write) at a time an entry containing of managed types. This is absurd. Managed types are pointers to memory. Reading and writing them to the stream is pointless. Therefore, for data whose length is unknown, you can only use sequential byte-by-byte reads, and not the entire structure at a time. It is clear that in this case, the packed declaration for records is meaningless.
Need to change the algorithm. Read and write record fields by one of the stream, byte-by-byte, or built-in TStream functions that have already been mentioned, such as ReadString, ReadDWord, etc.
My problem turned out to be that I was performing TStream.Read into a dynamic array, but I only specified the variable of the array itself and so the pointer (and following memory) was destroyed.
My problem turned out to be that I was performing TStream.Read into a dynamic array, but I only specified the variable of the array itself and so the pointer (and following memory) was destroyed.
And you did a Read with Size=0.Without digging into that, I would consider that reading a count of 0 bytes should be reading nothing and shouldn't raise an exception. But that's a different matter.
Without digging into that, I would consider that reading a count of 0 bytes should be reading nothing and shouldn't raise an exception. But that's a different matter.
Without digging into that, I would consider that reading a count of 0 bytes should be reading nothing and shouldn't raise an exception. But that's a different matter.
I stand corrected, it is not the read with size=0 that raises the exception, but accessing Data[0], because we just did SetLength(Data, Size).
Bart
Without digging into that, I would consider that reading a count of 0 bytes should be reading nothing and shouldn't raise an exception. But that's a different matter.
I stand corrected, it is not the read with size=0 that raises the exception, but accessing Data[0], because we just did SetLength(Data, Size).
Bart
What's the correct way to read into a dynamic buffer like that? Surely not the Data[0] thing.