GC and void[N] in struct

Steven Schveighoffer schveiguy at gmail.com
Mon Aug 6 19:43:17 UTC 2018


On 8/6/18 2:59 PM, vit wrote:
> On Monday, 6 August 2018 at 18:28:11 UTC, Steven Schveighoffer wrote:
>> On 8/6/18 2:22 PM, vit wrote:
>>> Hello,
>>> I have this struct:
>>>
>>> struct S{
>>>      uint kind;
>>>      void[N] data_;
>>
>> define "N"
>>
>>>
>>> }
>>>
>>> Instances of struct S are allocated by standard GC new and S.data_ 
>>> can contain pointers/ranges to GC allocated data.
>>> If is GC disabled then  program run fine. But when is GC enabled then 
>>> it fail randomly.
>>
>> how does it fail?
>>
> 
> 
> private auto sizeOf(T)(){return T.sizeof;}

Hm... wouldn't enum sizeOf(T) = T.sizeof work better?

> 
> struct ExprImpl(Ts...){
>      enum N = max(staticMap!(sizeOf, Ts));

This is clever!

> 
>      invariant(kind_ != 0);
>      uint kind_ = 0;
>      void[N] data_;
> 
>      this(T)(auto ref T x){/+emplace T to data_ and change kind_ to 
> something != 0+/}
> }
> 
> Ts == structs
> 
> 
> 
> data change without triggering invariant after allocation in other part 
> of program.

Most definitely this is alignment problem.

Here is what I *think* is happening:

1. You are constructing one of these structs, and storing a pointer as 
the T type.
2. You are on a 64-bit CPU.
3. The pointer is misaligned on the CPU, so when the GC scans this 
struct to see if it's pointing at anything, it sees one half as the 
kind_ value, and the other half is half of the pointer.
4. It misses the object being pointed at by the T inside the struct, and 
collects it, leaving a dangling pointer.
5. Memory corruption.

when you put the void[N] member *first*, it can properly align the item 
(most cases where the compiler is placing data, it starts out aligned) 
but this does not guarantee you have proper alignment, as void[N] has no 
alignment constraints.

I'd recommend instead, changing the uint kind_ to a size_t. This not 
only aligns the void[N] to size_t size, which should put any pointers in 
the right place, but it also makes sure the entire struct is aligned.

-Steve


More information about the Digitalmars-d-learn mailing list