Re: memory layouts of C++ classes

jangr@microsoft.com (Jan Gray)
Thu, 18 Aug 1994 19:27:47 GMT

          From comp.compilers

Related articles
memory layouts of C++ classes tomtzigt@frc602.intel.com (1994-08-12)
Re: memory layouts of C++ classes cliffc@rice.edu (1994-08-14)
memory layouts of C++ classes ssimmons@convex.com (1994-08-14)
Re: memory layouts of C++ classes jangr@microsoft.com (1994-08-18)
| List of all articles for this month |
Newsgroups: comp.compilers
From: jangr@microsoft.com (Jan Gray)
Keywords: C++, design, code
Organization: Microsoft Corporation
References: 94-08-087 94-08-091
Date: Thu, 18 Aug 1994 19:27:47 GMT

>tomtzigt@frc602.intel.com (Theodore Omtzigt - MAP-Folsom) writes:
>
> After walking the heap to reverse engineer the memory layout
> of a class in MFC, I figured this forum might provide a better
> answer. How does a C++ compiler build the memory layout of a class
> and a derived class? Also, what is the difference in memory layout
> of a regular C++ compiler and the memory layouts used by SOM compilers
> to provide binary consistency? Thanks in advance,




For the so-called Microsoft C++ Object Mapping, the object layout
algorithm for a given class is approximately:


0. start with an empty struct;


1. add a virtual function table pointer (vfptr) if this class
      has new virtual functions and does not inherit a vfptr from the
      non-virtually-inherited parts of some direct non-virtual base class;


2. add a virtual base displacement table pointer (vbptr) if this
      class has virtual bases and does not inherit a vbptr from the
      non-virtually-inherited parts of some direct non-virtual base class;


3. add an embedded instance of the non-virtually-inherited parts of each
      direct non-virtual base class, in declaration order;


4. add the non-static data members in declaration order;


5. add an embedded instance of the non-virtually-inherited parts of each
      direct or indirect virtual base class, (if I recall correctly) in the
      order found given a depth-first left-to-right preorder traversal of
      the base class graph.


(Intentionally avoiding discussion of the details of bitfields, padding
for alignment, virtual function tables, virtual base displacement tables,
"adjuster thunks", 0-sized bases, transitive virtual bases, the dreaded
"construction displacement" mechanism, etc., etc.)




As for SOM for C++, it purports to insulate compiled client code from some
kinds of class library changes. In general, this is achieved by using
variable, run-time summed, displacements and sizes of things rather than
constants and compile time constant folding, as the more conventional
C++ mappings use. So, conventionally, the code/data
struct M { virtual void foo(); };
struct X { X(); M* m; };
...
X x;
x.m->foo();
would be mapped to put x at some displacement on the frame, and then to
load a register with &x.m (at n(fp)) and call indirect through the first
vtable entry of x.m (or do something even more clever).


Under SOM, changes to X might cause sizeof(X) to change, and so-forth,
so for "x", it must alloca(current-sizeof(X)), must keep that address
somewhere, must add the current-displacment-to-m, and call a helper
function to call indirect through the current-vtable-entry of M::foo().
Variables like "current-sizeof(X)", "current-displacement-to-m",
and "current-vtable-entry" are established at load time.


Nothing is free. Whatever flexibility SOM for C++ provides would seem
to incur a substantial code quality penalty (especially all those
new alloca's, pointers, and aliases)...


Cheers.
Jan Gray // Microsoft Visual C++ Development


[bias disclosure: my employer would prefer you consider our "component
object model" (COM) as the substrate for your robust object system needs.]
--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.