Thread overview
[Issue 19539] Interface address is offset by 16bytes, causing memory leaks
Jan 02, 2019
Dru
Apr 24, 2019
Seb
Dec 17, 2022
Iain Buclaw
Oct 03, 2023
Mai Lapyst
January 02, 2019
https://issues.dlang.org/show_bug.cgi?id=19539

Dru <ihcuo21@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Interface address is offset |Interface address is offset
                   |16bytes, causing memory     |by 16bytes, causing memory
                   |leaks                       |leaks

--
April 24, 2019
https://issues.dlang.org/show_bug.cgi?id=19539

Seb <greeenify@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |bootcamp
                 CC|                            |greeenify@gmail.com

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=19539

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P2

--
October 03, 2023
https://issues.dlang.org/show_bug.cgi?id=19539

Mai Lapyst <info@lapyst.by> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |info@lapyst.by
         Resolution|---                         |INVALID

--- Comment #1 from Mai Lapyst <info@lapyst.by> ---
This is actually correct. This happends because of the way interfaces are implemented in machine code.

First of we need to understand how AX is layed out in memory:
---
<vtable>, <monitor>, <vtable for interface A>, <...rest of AX's fields>
---

Since vtable and monitor are both pointers, skipping 16 bytes means we now have the interface's vtable at the head. This is more effective in the long run for looking up methods to be called.

Secondly we need to know how exactly interface methods are invoked. One would belive that 'a.func()' simply would call 'func()' of 'AX' but thats not quite right. D (like many other languages) compiles here so called "thunk-functions", which essentially are specialized wrapper function that know what original method we're wanting to call and how to get from the modified pointer that 'a' has, back to the original pointer of 'ax', so that 'func()' still has all the data it needs. In this case it simply subtracts 16 bytes from the pointer, landing at exactly the original address.

This same behaviour is also the magic that make inheritance work in the first place.

If you print the address of 'this' inside 'func()' you'll see we got the
orginal address back.

Also: If you run 'writeln(cast(void*)cast(AX)a);', you'll also get the original
address back :)

--