D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6204 - emplace() for classes accepts larger chunk but fails in array assignment
Summary: emplace() for classes accepts larger chunk but fails in array assignment
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: Other Linux
: P2 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-06-24 00:20 UTC by Ali Cehreli
Modified: 2011-12-04 10:58 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Ali Cehreli 2011-06-24 00:20:13 UTC
This is tested with dmd 2.053 release version.

In the class version of emplace(), the following enforce indicates that it is legal to have a chunk larger than the instance size:

    enforce(chunk.length >= __traits(classInstanceSize, T),
           new ConvException("emplace: chunk size too small"));

Unfortunately, the following array assignment fails when that's the case:

    // Initialize the object in its pre-ctor state
    (cast(byte[]) chunk)[] = typeid(T).init[];

Here is a program that reproduces the issue:

import std.conv;

class C
{
    int i;
}

size_t alignedSize(T)()
{
    return (__traits(classInstanceSize, T) + T.alignof - 1)
        / T.alignof * T.alignof;
}

void main()
{
    enum roomPerObject = alignedSize!C();

    ubyte[roomPerObject] buffer;
    void[] placeForObject = (buffer.ptr)[0..roomPerObject];

    emplace!C(placeForObject);
}

The last line throws at runtime:

object.Exception@src/rt/arraycat.d(31): lengths don't match for array copy

A proposed fix would be to assign only to the first part of the chunk:

    (cast(byte[]) chunk)[0..__traits(classInstanceSize, T)] = typeid(T).init[];

(Note the range on the left hand side of the assignment.)

That gets rid of the problem but I am not sure about what to do with the potentially-non-zero remaining bytes of the chunk. The caller may assume that they will be cleared by emplace().