Re: ClassDef() Increases class size? + a Question to CINT gurus

From: Peter Lipa (lipa@nsma.arizona.edu)
Date: Thu May 20 1999 - 23:14:13 MEST


Hi Murik and fellow Rooters,

I just  had a similar problem and after days of hacking and reading the C++
standard carefully again
I found the following that might be your basic problem (and which has
nothing to do with
ClassDef() macros, but with interpreted versus compiled code!).

In C++ the size of a class, struct and  union is *NOT* necessarily equal the
sum of bytes
of its members!! That means a C++ compiler/interpreter is allowed to assign
any size
it wants to following struct (same for class and union)

struct Test_t  {
    Char_t   c;
    Short_t   i;
}  testStruct;

Naively (and rightly so) you would expect to get  a sizeof(testStruct) = 3.
This you will get e.g. with the gcc compiler and default flags.
HOWEVER a compiler is free to assign ANY size it wants (in practice
they often align the struct boundaries on multples of 8 bytes for efficiency
reason -
so does e.g. the Microsoft VC++ compiler by default), i.e. they "pad"  the
testStruct (of
naive size 3) with 1 or even 5 bytes!! Therefore an array of structs, e.g.

Test_t  testArray[10];

will be 80 bytes long instead of 30 (with 5 byte gaps between each struct
element).

This is exactly the case with the CINT interpreter. On my (WinNT and
Sun/Solaris) versions
CINT assigns 8 bytes to above struct:

root [0] struct Test_t { Char_t c; Short_t i;} testStruct
root [1] sizeof(testStruct)
(int)8
root [2] Test_t testArray[10]
root [3] sizeof(testArray)
(int)80

BOTTOM LINE:
You CANNOT assume  sizeof(struct/class/union) = sum of member sizes!!!
If code relies on this (because it happens to work on one compiler) it is
certainly not
portable.
You *CANNOT*   EQUIVALENCE/union a  C++ class/struct with a continuos
storage (fortran or
C/C++) array in a portable manner! (I fell into this pitfall too).
It is ANSI-C++'s  fault not ROOT/CINT's (the latter apparently chooses the
most efficent 8-byte alignment...).

If you want to read a fortran array into a class you have to copy
member-by-member from the appropriate
array elements in a loop.

So far my experience with that alignment ambiguity problem.
Now a question to CINT experts:

Most compilers have a switch to turn "struct/class/union-alignments" on/off
or to specific value (2,4, 8).
I haven't found any similar option for CINT. Is there a switch for CINT ????
Also, is there a way to define a certain aligment choice for a specific
struct and another one for the next struct/class
(I am thinking/hoping of some #pragma switch) ??
Even if not required by the C++ standard, it would be nice to have...

Thanks in advance
Peter





----- Original Message -----
From: Maurik Holtrop <maurik.holtrop@unh.edu>
To: roottalk <roottalk@hpsalo.cern.ch>
Sent: Thursday, May 20, 1999 11:47 AM
Subject: ClassDef() Increases class size?


> Hello Root,
>
> I seem to be running into a problem with ClassDef (and ClassImp)
increasing
> the size of my class's storage area by about 4 bytes. I am *not* deriving
> from TObject, so the extra bytes are not from there.
> Is there a way around this which will still give me all the nice features
> (streamer, showmember etc) of ROOT but keep my class the exact same size
as
> the data members I defined?
>
> The reason that the extra bytes are a problem is because I am setting
> pointers into an already existing array with data (which is created by a
> FORTRAN package called BOS), in order to read it's contends. The extra
bytes
> causes the next pointer to be 4 bytes off.
>
>     Maurik
>
>
> --------------------------------------------------------------------------
-------
>
> Sample code:
>
> The following code will have a "sizeof()" of 56 instead of the expected
52:
>
> class TPARTData  {
>  public:
>   Int_t     pid;                     /*   particle id
> (GEANT)                              */
>   Float_t   x;                       /*   vector3_t vert; Vertex position
> {x,y,z}          */
>   Float_t   y;                       /*
> y                                                */
>   Float_t   z;                       /*
> z                                                */
>   Float_t   e;                       /*   vector4_t p;
> Energy                              */
>   Float_t   px;                      /*   momentum
> {x,y,z}                                 */
>   Float_t   py;                      /*
> py                                              */
>   Float_t   pz;                      /*
> pz                                               */
>   Float_t   q;                       /*
> charge                                           */
>   Int_t     trkid;                   /*   index to TBID bank, counting
from
> 1              */
>   Float_t   qpid;                    /*   quality factor for the
> pid                       */
>   Float_t   qtrk;                    /*   quality factor for the
> trk                       */
>   Int_t     flags;                   /*   set of flags defining track (ie,
> BEAM)           */
>
>   ClassDef(TPARTData,1)
>
> };
>
>



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:33 MET