0

I'm working on a solution that should work in C++-Builder and Delphi, that's why I use Object Pascal syntax, but I'm not very familiar with it. I try to access a file mapping with a size that is not defined at runtime with Free Pascal/Delphi. I tried

type
  TFileMappingLayout = packed record
    Size: DWORD;
    Data: array [0..0] of byte;
  end;
  PFileMappingLayout = ^TFileMappingLayout;

but I'm not sure if this is conform with range checking. It seems to be impossible to google for it, I found nothing useful so far. Reading descriptions about creating structured types did not mention cases like this. I also had a look into the Lazarus source code, but I gave up after 100 trivial record definitions...

I use the Data field only for binary copying, for instance, writing to it:

  PFileMappingLayout(FData)^.size := cbData;
  Move(myData, PFileMappingLayout(FData)^.Data, cbData);

How is this normally done in Delphi/Free Pascal?

How would you name this kind of record definition (open record, partial record)?

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
Wolf
  • 630
  • 1
  • 6
  • 24
  • Apparently I accidentally "reinvented" a common stereotype. I just had the idea to regex search for `\[0\.\.0\]` in the same source code and found 817 matches. The only thing I missed is the comment `{ variable size, determined by Size }`. I'm **still interested in the name of this kind of record** (hopefully also some language reference link). – Wolf Oct 20 '15 at 11:50
  • 1
    Make sure you turn RANGE CHECKING OFF if you try stuff like this: `{$R-}` I would be tempted to actually declare a useful large size like Data:array[0..4096] and then simply make sure you don't access beyond the real range, then you won't run afowl of the built in range checking operations in Delphi. – Warren P Oct 28 '15 at 20:33
  • @WarrenP I'm not sure is this is necessary, when using the `Move` function on the address where `Data` starts in above example. IOW: I never use the `[]`-syntax. – Wolf Dec 09 '15 at 13:57

1 Answers1

1

To avoid range-check errors, you should rather define the data array as follows:

Data: array[0..MaxInt-1] of Byte;

In general, for a type TMyType, you can define such an open-ended array as follows:

Data: array[0..MaxInt div SizeOf(TMyType) - 1] of TMyType;

But this is all if you specifically want to have a record structure as you currently have. Personally I would just use a dynamic array:

Data: array of Byte;

Use SetLength() to initialize its count and Length() to get its current count. You don't have to allocate or de-allocate any memory for this as you would have to for your implementation.

(Sorry, I don't know what they call such record types as you indicated...)

Jannie Gerber
  • 111
  • 1
  • 1
  • 3
  • The structure I define is for accessing the view on the shared memory Windows gave me. I have a base pointer to it and don't want to cast too much, that's why I'm trying to avoid "naked" pointer arithmetic. The structure I defined is only a casting tool. I think range checking should not being applied when I use `Move` - is this assumption correct from your experience? – Wolf Dec 09 '15 at 13:52
  • 2
    @Wolf, if you're just going to use `Move`, then you actually don't even need an array at all. you could just define a one-byte field and reference that (as you are currently referencing the array without index). But, yes, if you keep it an array and never actually index into the array, range-checking won't come into play. – Jannie Gerber Dec 09 '15 at 14:03
  • Thanks. I thought `array [0..0] of byte` (which is also exactly 1 byte in size) would make my intention more clear to co-programmers (and maybe to me as well sometimes), and since I found [lots of it](https://programmers.stackexchange.com/questions/300340/records-defining-a-partial-memory-layout/304637?noredirect=1#comment624820_300340) in the Lazarus/Free Pascal code, I guess it's a common stereotype. Well ;-) the question after the name is still open... – Wolf Dec 09 '15 at 14:17
  • 1
    @Wolf, I have to agree - the array version does make your intention clearer. It's only when you actually index into it that range checking becomes a problem, but then you can use the `MaxInt` version. As for the name, maybe "variable record" to indicate variable size? Variant record is of course used for when parts of the record is redefined... – Jannie Gerber Dec 10 '15 at 07:45
  • If you find the time to update your answer to better match the actual question, I'd be happy to +1 it. – Wolf Dec 10 '15 at 11:29
  • @Wolf, I'm not sure what change I should make. He asked how it's normally done and I gave him two options - one a correction to his method that avoids range-checking errors and one that uses a dynamic array as a buffer. The correct name for his record type I don't know (just guessing in my comment above). I'm still feeling my way on the Stack Exchange sites; so any pointers for improving the answer will be appreciated. – Jannie Gerber Dec 11 '15 at 09:44