struct / cast / ? design problem

Charles Hixson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Mar 16 11:18:16 PDT 2015


On 03/16/2015 09:16 AM, Charles Hixson via Digitalmars-d-learn wrote:
>
> On 03/15/2015 04:51 PM, ketmar via Digitalmars-d-learn wrote:
>> On Sun, 15 Mar 2015 16:34:14 -0700, Charles Hixson via 
>> Digitalmars-d-learn
>> wrote:
>>
>> if you know the exact layouts of `spare`, you can use union for that:
>>
>> struct S {
>>    // ...
>>    union {
>>      ulong[61] spare;
>>      struct { int vala; ubyte valb; }
>>      // etc.
>>    }
>> }
>>
>> and then you can use it like this:
>>
>>    auto s = S();
>>    s.vala = 42;
>>    assert(s.spare[0] == 42);
>>
>> you can also write a CTFE function that builds struct to cast where
>> `spare` is changed to something else, using `S` as a source, but this
>> solution will not be pretty. ;-)
> The original method had no knowledge of the layout that the using 
> module will need, merely that it will need to store some information.  
> (In this particular case I *could* just modify the header in the 
> original file, but that isn't solving the design problem, and means 
> that working code needs to be modified to accommodate new code in a 
> different file.)
>
> IOW, if I could write the union, I wouldn't have needed to label the 
> unused header memory "spare".  That solution *would* allow for 
> multiple secondary users, with different union values, but it would 
> again mean that new code would require the modifying of the file 
> containing existing code.  This is normally considered bad practice.
>
>
My current best answer is to turn the "unused" into a vector of bytes, 
and then pass that to the using routines as a ref.  This still is wide 
open to errors at the calling end, but the BlockHead end can ensure that 
the length of the vector remains constant whenever it accesses it (well, 
whenever the head is being written to disk.  The byte vector would be a 
static array at the BlockHead end.  This would seem to allow the using 
end to cast the byte vector into an appropriate struct for its own use, 
and that writes to it would be seen by BlockHead as writes to the 
header...but only to restricted parts of the header.  The problem here 
is that the ref array might allow itself to be resized at the user end.  
That's not a problem as long as the resizing is to something smaller, 
but I'm not sure what happens if it gets resized to something larger.  
It looks like allowing a buffer overflow.


More information about the Digitalmars-d-learn mailing list