View Issue Details

IDProjectCategoryView StatusLast Update
0031418FPCDocumentationpublic2017-03-17 14:59
ReporterLycheeAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityN/A
Status resolvedResolutionfixed 
Product Version3.0.0Product Build 
Target Version3.2.0Fixed in Version3.1.1 
Summary0031418: Issues with structured types alignment documentation
DescriptionThe paragraph 8.3.2 Structured types alignment [*] reads:
> For example a record or object having a 1 byte element, will have its
> size rounded up to 2, so the size of the structure will actually be 2 bytes.

The code in steps to reproduce prints out a value 1 for me, in contradiction to what the documentation reads.

That would imply that either the code below produces the wrong result or the documentation is not entirely correct.

Obviously, i opted for the documentation being wrong there.

[*] http://www.freepascal.org/docs-html/3.0.0/prog/progsu172.html#x217-2300008.3.2
Steps To Reproduceprogram test;
Type
  TOneByteRecord = record
    One: Byte;
  end;
var
 x: TOneBytyeRecord
begin
  WriteLn(SizeOf(x));
end.
TagsNo tags attached.
Fixed in Revision1406
FPCOldBugId
FPCTarget
Attached Files

Activities

Thaddy de Koning

2017-02-20 08:29

reporter   ~0098326

Last edited: 2017-02-20 08:41

View 7 revisions

Yes, there is a special case here: If the record contains just one field of type byte the size is indeed 1 in all modes. But there are no further record fields to align relative to each other.
There is logic in that: there is nothing to align. Align means that the record *fields* are aligned *relative* to each other. You have just one field.
Once you add fields after the byte field there is something to align and the documentation is correct.

What is strange, though, that you would expect - based on your expectations - a record like:
program test;

Type
  TOneByteRecord = record
     two:integer;
     One: Byte;
  end;

begin
  WriteLn(SizeOf(TOneByteRecord));
end.

To also be always 3, but that is 4. (I always assumed 4 or 8, btw)
Maybe the special case should be documented but it is a border case.

What's also missing in this particular chapter is that it is not only dependent on align settings, but also on mode: The above code assumes default or TP mode where integer is 16 bit.
In other modes, like ObjFpc or Delphi, the size is 8 (where you would expect 6), because the integer size is 4. And that is not a border case.

Summarize:
- Record with just one field of type byte has a size of 1 in all modes.
- Default alignment is not 2 but depends on the integer size of the mode.

That is indeed missing from the documentation.

Lychee

2017-02-20 14:24

reporter   ~0098337

There is unfortunately a lot missing from documentation imho.

One of the most influential changes is mention here [1];

From that i read that nothing can be assumed about the size of a record since it depends on what the compiler thinks is best. e.g. padding last byte(s) can change from case to case

At first glance it appears that one is manually responsible for the correct padding in case wanting to keep the same record working for both little and big endian systems, and using variant records with overlapped fields seems even more difficult to maintain.

At least i seem unable to change the mind of the compiler, and that leads to some very strange behavior (at least strange in my mind). For instance no matter the codealign recordmin, last field seems not being padded (and that is correct in principle) but causes confusion if wanting to have a static record-size.

But, i digress.

Please, let's do small steps. First remove not entirely correct statements, then add new extensive documentation on how things actually (should) work :-)

[1] http://wiki.freepascal.org/User_Changes_2.4.0#Alignment_of_record_variables

Thaddy de Koning

2017-02-21 05:55

reporter   ~0098352

Last edited: 2017-02-21 06:06

View 5 revisions

Mm. I missed that, but that is almost exactly what I found during testing.
Suggest to update the documentation according to the description in the user changes from 2.4 since that exactly covers it.

The description is especially important because it follows that unpacked records can not reliably be used for file IO because of the way the compiler can optimize alignment. I know that,but many people don't.

Michael Van Canneyt

2017-03-17 14:59

administrator   ~0098968

I consulted with the rest of the team. The documentation of PACKRECORDS is correct, I have adapted the section about structure types alignment so it states that default alignment is natural alignment, but that it can be influenced using PACKRECORDS.

Issue History

Date Modified Username Field Change
2017-02-20 04:48 Lychee New Issue
2017-02-20 04:48 Lychee Status new => assigned
2017-02-20 04:48 Lychee Assigned To => Michael Van Canneyt
2017-02-20 08:29 Thaddy de Koning Note Added: 0098326
2017-02-20 08:33 Thaddy de Koning Note Edited: 0098326 View Revisions
2017-02-20 08:33 Thaddy de Koning Note Edited: 0098326 View Revisions
2017-02-20 08:37 Thaddy de Koning Note Edited: 0098326 View Revisions
2017-02-20 08:39 Thaddy de Koning Note Edited: 0098326 View Revisions
2017-02-20 08:40 Thaddy de Koning Note Edited: 0098326 View Revisions
2017-02-20 08:41 Thaddy de Koning Note Edited: 0098326 View Revisions
2017-02-20 14:24 Lychee Note Added: 0098337
2017-02-21 05:55 Thaddy de Koning Note Added: 0098352
2017-02-21 05:56 Thaddy de Koning Note Edited: 0098352 View Revisions
2017-02-21 06:00 Thaddy de Koning Note Edited: 0098352 View Revisions
2017-02-21 06:01 Thaddy de Koning Note Edited: 0098352 View Revisions
2017-02-21 06:06 Thaddy de Koning Note Edited: 0098352 View Revisions
2017-03-17 14:59 Michael Van Canneyt Fixed in Revision => 1406
2017-03-17 14:59 Michael Van Canneyt Note Added: 0098968
2017-03-17 14:59 Michael Van Canneyt Status assigned => resolved
2017-03-17 14:59 Michael Van Canneyt Fixed in Version => 3.1.1
2017-03-17 14:59 Michael Van Canneyt Resolution open => fixed
2017-03-17 14:59 Michael Van Canneyt Target Version => 3.2.0