comp.lang.c
[Top] [All Lists]

Re: struct versioning

Subject: Re: struct versioning
From: Chris Torek
Date: 29 Apr 2008 17:12:45 GMT
Newsgroups: comp.lang.c

In article <fv7i4t$hco$1@xxxxxxxxxxxxxxx> Pres <invalid.email@xxxxxxxx> wrote:
>Noticed that several windows API's take a size parameter.
>i.e. one of the members of the struct is dwSize which is supposed
>to be initialized by client code, by taking the sizeof of the struct.
>
>I assume this is to enable versioning of structures ...

It might be; but using sizes for version information is, er, "not
very clever".  Consider, e.g., what happens if a "V1" data structure
has a total of 12 bytes of information, V2 adds four (giving 16),
V3 adds another 8 (now 24), and then V4 simplifies it all and
shrinks the number down to 20.  When V5 comes out, and needs four
more byte of information, the "24" size will have already been in
use (in V3).

In other words, if you want a *version* tag, use a version tag,
not a size tag.

>Is my assumption correct - is this something like what they would
>be doing?

(I have no idea.  It is hard enough to speculate on what someone
intended when you have access to all of the code; give me just a
vague description and it becomes that much harder.)

>Is this fully standard compliant or are they taking liberties with their
>close knowledge of the internals of the compiler.

There is nothing "nonstandard" about it, but nothing particularly
"standard" either.  "Taking liberties" is not really a justifiable
claim at this point though:

>Assume lib_v1 is compiled with compiler cl_v1 & lib_v2 is compiled
>with compiler cl_v2, then it is safe to assume that sizeof(A_v1) would
>be the same when compiled with different versions of the same compiler?

This is never a completely *safe* assumption.  Any two different
compilers could do different things.  However, if the two are
*intended* to inter-operate -- as is usually the case for a newer
version of a compiler from the same vendor -- then things that
change the size (and hence layout) of struct types are generally
viewed as "bugs" in the compiler. :-)  The reason is that changing
*anything* about the layout and/or representation results in
"binary incompatibility" with the other (or previous) compiler.

Consider, for instance, CPUs with "endian-ness" bits in instructions.
(Typically a load or store instruction, on such a CPU, has an
endian-control bit, so you might do:

   load_little_endian  r1, mem
   load_big_endian     r2, mem

and so on.  The spelling of this instruction is "lda" on the SPARC
and the endian-ness is provided as a third argument, but it is
encoded in the instruction nonetheless[%].  The "lda" instruction
runs just as fast as the "non-annotated" "ld" instruction, too.
The regular "ld" instruction takes the endian-ness from the CPU
endian-ness control.)  On such a CPU, we can write incompatible
compilers (or incompatible compiler versions) just by changing the
endian-ness controls.  This has no effect on the *sizes* of the
data being loaded and stored, just on the in-memory representations.

>i.e. can sizeof(A_v1) can when compiled with gcc v2 as compared to
>gcc v1?  ... can it change when compiled by two totally different
>compilers?

It can, but these are often considered bugs.  However, consider
what happens if you use compiler "packing" switches, either from
things like #pragma or from command-line switches ("-fpack-struct",
"/pack:N", "optimize=memfootprint", etc).  Using these is like
changing implementations: the code you get with "pack-all-structs"
is not binary-compatible with the code you get without it.

[% Actually, this varies: you can either have it inside the
instruction, or in the %asi register, as I recall.  If it is in
the instruction, you must give up the offset addressing modes.]
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W)  +1 801 277 2603
email: gmail (figure it out)      http://web.torek.net/torek/index.html

<Prev in Thread] Current Thread [Next in Thread>
Privacy Policy