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) |
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.]
--
Return to the
comp.compilers page.
Search the
comp.compilers archives again.