Regarding emplace, arrays, and helper functions
Ali Çehreli
acehreli at yahoo.com
Thu Aug 29 20:10:17 PDT 2013
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 at 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
More information about the Digitalmars-d-learn
mailing list