On 08/29/2013 05:20 AM, Andrej Mitrovic wrote:

> The emplace docs state that the chunk where to store the class object
> instance needs to be aligned to the class type alignment. But it
> doesn't say much on how to get this alignment from a class (we could
> add a note about using the classInstanceAlignment template), or even
> how to use it to create e.g. an array of class objects (not an array
> of references).
>
> Here's how one can run into a problem:
>
> -----
> import std.conv;
>
> class C
> {
>      this(ubyte b) { _b = b; }
>      ubyte _b;
> }
>
> void main()
> {
>      // 9 bytes (x32), it's not going to align itself properly
>      enum Size = __traits(classInstanceSize, C);
>
>      ubyte[Size][2] buffer;
>
>      // off-topic: cast needed -> yet another emplace bug
>      auto obj1 = emplace!C(buffer[0], cast(ubyte)20);
>      assert(obj1._b == 20);
>
>      auto obj2 = emplace!C(buffer[1], cast(ubyte)20);  // Boom!
>      assert(obj2._b == 20);
> }
> -----
>
> On the second emplace call, an exception is thrown:
>
> -----
> std.conv.ConvException@std\conv.d(3832): emplace: Misaligned memory
> block (0x18FD41): it must be 4-byte aligned for type C
> -----
>
> So one has to figure out how to do alignment properly, but there's no
> real documentation on how to do it.

I had experimented with this in a chapter (not in English yet):

  http://ddili.org/ders/d/bellek_yonetimi.html

Here are two functions that I have just translated from that page (I see that alignedAddress should better be alignUp):

T * alignedAddress(T)(T * candidateAddress)
out (result)
{
    assert((cast(size_t)result % T.alignof) == 0);
}
body
{
    return cast(T*)((cast(size_t)candidateAddress + T.alignof - 1)
                    / T.alignof * T.alignof);
}

size_t paddedSize(T)()
{
    static if (is (T == class)) {
        size_t size = __traits(classInstanceSize, T);

    } else {
        size_t size = T.sizeof;
    }

    return cast(size_t)alignedAddress(cast(T*)size);
}

Now your program works with a single change:

    enum Size = paddedSize!C();

Ali

Reply via email to