Debug help - Programming in D, page 670 allocate buffer of 10 MyClass class instances

Brother Bill brotherbill at mail.com
Wed Sep 3 12:10:17 UTC 2025


On Wednesday, 3 September 2025 at 03:09:45 UTC, Ali Çehreli wrote:
> GC.calloc(bytesNeeded);
>
> Again, I misled you there.
>
> >      writeln("myClasses address: ", myClasses);
> >
> >      alias MyClassPtr = MyClass *;
>
> That's not useful because the type MyClass is already a 
> reference type, implemented as a pointer by the compiler.
>
> Yes, pointer to a class type will make sense in some cases but 
> not here.
>
> >      MyClassPtr[10] myClassPtrs;
>
> So, that could be MyClass[]. Note, not the objects but MyClass 
> values will be stored there, which are references to MyClass 
> objects.
>
> >      foreach (i; 0 .. 9) {
>
> I removed hard-coded 10 above because your loop was one less 
> than 10 iterations.
>
> Ali

Made some further changes, and have additional questions.

Console output:
```
myClassActualSize: 41
myPaddedClassSize: 48
bytesNeeded: 480
myClasses address: 25DF6931000

0: {a: 0, name: Sally, c: D}, &myClasses[i]: 25DF6932000, 
&myClasses[i].a: 25DF6931010
1: {a: 1, name: Sally, c: D}, &myClasses[i]: 25DF6932008, 
&myClasses[i].a: 25DF6931040
2: {a: 2, name: Sally, c: D}, &myClasses[i]: 25DF6932010, 
&myClasses[i].a: 25DF6931070
3: {a: 3, name: Sally, c: D}, &myClasses[i]: 25DF6932018, 
&myClasses[i].a: 25DF69310A0
4: {a: 4, name: Sally, c: D}, &myClasses[i]: 25DF6932020, 
&myClasses[i].a: 25DF69310D0
5: {a: 5, name: Sally, c: D}, &myClasses[i]: 25DF6932028, 
&myClasses[i].a: 25DF6931100
6: {a: 6, name: Sally, c: D}, &myClasses[i]: 25DF6932030, 
&myClasses[i].a: 25DF6931130
7: {a: 7, name: Sally, c: D}, &myClasses[i]: 25DF6932038, 
&myClasses[i].a: 25DF6931160
8: {a: 8, name: Sally, c: D}, &myClasses[i]: 25DF6932040, 
&myClasses[i].a: 25DF6931190
9: {a: 9, name: Sally, c: D}, &myClasses[i]: 25DF6932048, 
&myClasses[i].a: 25DF69311C0
```

source/app.d
```
import std.stdio;
import std.string;
import core.memory;
import core.lifetime;

void main()
{
	enum elementCount = 10;

     // Allocate room for 10 MyClass objects
     immutable size_t myClassActualSize = 
__traits(classInstanceSize, MyClass);
     writeln("myClassActualSize: ", myClassActualSize);

     // ensure myClassSize is divisible by 8, to allow for padding
     immutable padding = 8;
     immutable size_t myPaddedClassSize =
         (myClassActualSize % padding == 0)
			? myClassActualSize
			: (myClassActualSize + padding) / padding * padding;
     writeln("myPaddedClassSize: ", myPaddedClassSize);

     immutable bytesNeeded = myPaddedClassSize * elementCount;
     writeln("bytesNeeded: ", bytesNeeded);

     void* myClassObjects = GC.calloc(bytesNeeded);
     writeln("myClasses address: ", myClassObjects);

     // [Ali] Note the type of the array:
	//       MyClass is a reference to object; no pointer needed
     MyClass[] myClasses;

     foreach (i; 0 .. elementCount) {
         void * address = myClassObjects + (i * myPaddedClassSize);

         // The first parameter guides emplace() of slice to 
instantiate MyClass instance.
         myClasses ~= emplace!MyClass(address[0 .. 
myPaddedClassSize], i, "Sally", 'D');
     }
	writeln;

	foreach (i; 0 .. elementCount) {
		writefln("%s: %s, &myClasses[i]: %s, &myClasses[i].a: %s",
				  i, myClasses[i], &myClasses[i], &myClasses[i].a);
	}
}

class MyClass
{
     int a;
     string name;
     char c;

     this(int a, string name, char c) {
         this.a = a;
		this.name = name;
		this.c = c;
     }

	override string toString() const {
		return format("{a: %s, name: %s, c: %s}", a, name, c);
	}
}
```

Questions:
1. Is it necessary to pad myPaddedClassSize to an 8 byte 
granularity on 64 bit machine?
    If so, should emplace() be modified to provide the padding 
internally?

2. There is a 16 byte header before myClasses[0].a
    Is this for class overhead?


More information about the Digitalmars-d-learn mailing list