Address of a class object

Ali Çehreli acehreli at yahoo.com
Wed Jan 4 19:27:08 UTC 2023


On 1/4/23 10:48, H. S. Teoh wrote:

 > Allocations are not necessarily consecutive; the GC may have its own
 > strategy of allocation that doesn't follow a linear sequence.

That was one of my guesses. So, I put the objects into a 2-length static 
array but the difference was still 0x20. (?)

 > Furthermore, GC-allocated blocks may be larger than the request size
 > because there may be some extra management information stored in the
 > block (but outside the pointer range returned).

Good point. I think the minimum size of a dynamically allocated memory 
of the current GC implementation is 32 bytes.

I've just realized that I was confusing myself by thinking the object 
pointer that cast(void*) produces was the first member's address. I was 
wrong: That is the address of the first of the two hidden members (the 
vtbl pointer and the monitor).

My current guess is, although it could be a void*, the alignment of the 
first of those hidden members is 16.

Now that I have a more correct understanding, the following program 
prints those hidden members. One of the examples shows the monitor of an 
object used with 'synchronized' is non-null.

import std.stdio, std.traits;

class MyClass {
     char[1] c;
}

void main() {
     writeln(" Size  Alignment  Type\n",
             "=========================");

     size_t size = __traits(classInstanceSize, MyClass);
     size_t alignment = classInstanceAlignment!MyClass;
     writefln("%4s%8s      %s",size, alignment, MyClass.stringof);

     // Apologies for using lower-cased variable names. :)
     auto a = new MyClass();
     auto b = new MyClass();

     printObject!a;
     printObject!b;

     auto withMonitor = new MyClass();

     synchronized (withMonitor) {
         // This object's "hidden 1" (the monitor) will not be 'null'
         printObject!withMonitor;
     }

     // This object's "hidden 0" (vtbl pointer) will be different:
     class SubClass : MyClass {
     }
     auto sub = new SubClass();
     printObject!sub;
}

void printObject(alias obj)() {
     writeln("\n");
     writeln("name        : ", obj.stringof);

     const addr = cast(void*)obj;
     writeln("address     : ", addr);
     writeln("hidden 0    : ", hiddenValue(addr, 0));
     writeln("hidden 1    : ", hiddenValue(addr, 1));
}

void* hiddenValue(const(void)* obj, size_t index) {
     alias HiddenType = void*;
     auto ptrToHiddens = cast(HiddenType[2]*)obj;
     return (*ptrToHiddens)[index];
}

Here is the output:

  Size  Alignment  Type
=========================
   17       8      MyClass


name        : a
address     : 7F4009D48000
hidden 0    : 558A1E172520
hidden 1    : null


name        : b
address     : 7F4009D48020
hidden 0    : 558A1E172520
hidden 1    : null


name        : withMonitor
address     : 7F4009D48040
hidden 0    : 558A1E172520
hidden 1    : 558A20164B80  <-- non-null monitor


name        : sub
address     : 7F4009D48060
hidden 0    : 558A1E172630  <-- Different vtbl for sub-class
hidden 1    : null

Ali



More information about the Digitalmars-d-learn mailing list