Topic: What's the conclusion on the UAB?


Author: James.Kanze@dresdner-bank.com
Date: 1999/07/21
Raw View
In article <377C0643.CAC77E4B@tribble.com>,
  David R Tribble <david@tribble.com> wrote:

    [...]
> But why bother with all this?  Both the 'new' operator and the
> malloc() library function are guaranteed to provide memory areas
> properly aligned for any valid data type, including extended types.
> The C++ standard states, in fact, that dynamically allocating an
> array of type 'char[sizeof(T)]' is guaranteed to provide an area
> that can hold a valid object of type 'T'.
>
> The only use I can imagine for union UAB is for objects not
> dynamically allocated, i.e. auto or static objects.

The classical example is ensuring correct alignment for members declared
as raw memory:

    template< class T , int dim >
    class Array
    {
        //  ...
        char                buffer[ sizeof( T ) * dim ] ;
    } ;

In this case, presumably, buffer must be sufficiently aligned for a T ;
since it is declared as char[], however, there are good chances that
with some compiler, it won't be.

--
James Kanze                         mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                        Beratung in objekt orientierter
Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany  Tel. +49 (069) 63 19 86
27


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <david@tribble.com>
Date: 1999/07/15
Raw View
Andrei Alexandrescu wrote:
>
> UAB = Universally Aligned Buffer
>
> Purpose: define a raw buffer that's aligned with any object.
> You know, that trick of making an union of all types:
>
> union UAB
> {
>     char d1;
>     short d2;
>     int d2;
>     long d3;
>     float d4;
>     double d5;
>     long double d6;
>     void* d7;
>     class Prototype;
>     Prototype* d8;
>     void (Prototype::* d9)();
>     // what did I forget?
> };
>
> Now if I want to allocate a buffer able to hold a class T, I make an
> union containing UAB and char[sizeof(T)].
>
> The question is: just how portable this is? I'm not interested in "it
> works with compiler X on OS Y". I need true universal portability.

It is portable, since portable code can't use any non-standard
(extended) types beyond the basic types, and you've gone through all
the trouble of including all of the basic types in union UAB.  (Note
that all struct pointers smell alike, and are constrained to having
the same alignment; this is a consequence of the rules established
for ISO C; it is therefore sufficient to declare only one struct
pointer member in the union.)

You should add a function pointer member (which is not guaranteed to
be the same size or have the same alignment as data pointers) and a
bool member:

    void  (*d10)();
    bool  d11;

But why bother with all this?  Both the 'new' operator and the
malloc() library function are guaranteed to provide memory areas
properly aligned for any valid data type, including extended types.
The C++ standard states, in fact, that dynamically allocating an
array of type 'char[sizeof(T)]' is guaranteed to provide an area
that can hold a valid object of type 'T'.

The only use I can imagine for union UAB is for objects not
dynamically allocated, i.e. auto or static objects.

-- David R. Tribble, david@tribble.com --
   Those who do not study for-loops are destined to repeat them.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Jens Kilian <Jens_Kilian@bbn.hp.com>
Date: 1999/07/18
Raw View
David R Tribble <david@tribble.com> writes:
> But why bother with all this?  Both the 'new' operator and the
> malloc() library function are guaranteed to provide memory areas
> properly aligned for any valid data type, including extended types.

Um, perhaps because he intends to *write* an allocation function?

--
mailto:jjk@acm.org                 phone:+49-7031-14-7698 (HP TELNET 778-7698)
  http://www.bawue.de/~jjk/          fax:+49-7031-14-7351
PGP:       06 04 1C 35 7B DC 1F 26 As the air to a bird, or the sea to a fish,
0x555DA8B5 BB A2 F0 66 77 75 E1 08 so is contempt to the contemptible. [Blake]
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James.Kanze@dresdner-bank.com
Date: 1999/06/30
Raw View
In article <7kub48$j1d$1@nnrp1.deja.com>,
  Andrei Alexandrescu <andrewalex@hotmail.com> wrote:

> UAB = Universally Aligned Buffer
>
> Purpose: define a raw buffer that's aligned with any object.
> You know, that trick of making an union of all types:
>
> union UAB
> {
>     char d1;
>     short d2;
>     int d2;
>     long d3;
>     float d4;
>     double d5;
>     long double d6;
>     void* d7;
>     class Prototype;
>     Prototype* d8;
>     void (Prototype::* d9)();
>     // what did I forget?
      void (*pf)() ;
> };
>
> Now if I want to allocate a buffer able to hold a class T, I make an
> union containing UAB and char[sizeof(T)].
>
> The question is: just how portable this is?

Let me confirm: you are asking about portability, and *not* what the
standard says.

For practical portability, the maximum required alignment will be the
maximum required alignment of the basic types, plus the different
pointer representations supported by hardware.  And hardware design
constraints will ensure that there won't be more than three or four
pointer types.  (Hardware considerations also imply that things like
pointers to member functions will be implemented as a struct, and
compiler design considerations imply that a struct will not have
stricter alignment requirements than the most strict required for basic
types and pointers.)

The only real problem is finding the optimal C/C++ declarations for the
pointer types.  From practical experience, I would say that char*, a
pointer to function, and a pointer to the union itself (UAB*) should do
the trick.

I do *not* put pointers to members in the union.  A pointer to member
function, in particular, is sometimes quite big, an may force excess
memory use.

All of this, of course, only concerns practical portability.  The
standard doesn't guarantee it, and in fact, allows a different
representation (and thus, a different alignment requirement) for all
different pointer types (except pointers to structs, all of which use
the same representation).  Since the standard allows every enum pointer
to have a different representation and different alignment restrictions,
there is no way to define such a union so that the standard guarantees
maximum alignment.  IMHO, this is only a standards question, however,
and does not affect real portability.

> I'm not interested in "it
> works with compiler X on OS Y". I need true universal portability.

See above.  As far as I'm concerned, a union of the basic types, plus
char* (or void*), UAB* and a pointer to function will result in
universal portability, although not with a guarantee from the standard.

--
James Kanze                         mailto:
James.Kanze@dresdner-bank.com
Conseils en informatique orientie objet/
                        Beratung in objekt orientierter
Datenverarbeitung
Ziegelh|ttenweg 17a, 60598 Frankfurt, Germany  Tel. +49 (069) 63 19 86
27


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Andrei Alexandrescu <andrewalex@hotmail.com>
Date: 1999/06/25
Raw View
UAB = Universally Aligned Buffer

Purpose: define a raw buffer that's aligned with any object.
You know, that trick of making an union of all types:

union UAB
{
    char d1;
    short d2;
    int d2;
    long d3;
    float d4;
    double d5;
    long double d6;
    void* d7;
    class Prototype;
    Prototype* d8;
    void (Prototype::* d9)();
    // what did I forget?
};

Now if I want to allocate a buffer able to hold a class T, I make an
union containing UAB and char[sizeof(T)].

The question is: just how portable this is? I'm not interested in "it
works with compiler X on OS Y". I need true universal portability.

I know this has been posted a number of thread, but I didn't see a
definitive answer yet.

Andrei


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1999/06/26
Raw View
Andrei Alexandrescu wrote:
>
> UAB = Universally Aligned Buffer
>
> Purpose: define a raw buffer that's aligned with any object.
> You know, that trick of making an union of all types:
>
> union UAB
> {
>     char d1;
>     short d2;
>     int d2;
>     long d3;
>     float d4;
>     double d5;
>     long double d6;
>     void* d7;
>     class Prototype;
>     Prototype* d8;
>     void (Prototype::* d9)();
>     // what did I forget?

Infinitely many other things. Each different type of pointer could in
principle have it's own alignment restrictions (there are a few types of
pointers which are required to have compatible representations and
alignement requirements), and C++ allows a practically infinitely large
number of different pointer types to be declared. 'void *' must be big
enough to hold a reversible representation of any pointer to an object,
but that doesn't mean it couldn't have less severe alignment
restrictions than some of the pointer types it can be converted to.

An implementation is also allowed to have extended types, and to make
them available to strictly conforming code through standard typedefs
such as clock_t, and as members or member typedefs of standard classes
like 'struct tm' and std::list<int>. Therefore, you should also include
all of the standard typedefs and classes, and their member typedefs.
There are, of course, a practically infinite number of parameter
combinations for which any standard template class might be
instantiated. Any particular extended type, with arbitrarily severe
alignment restrictions, might only be used in the specialization of that
template for a particular T. Therefore, you must include every possible
specialization of every standard template.

If you want your UAB to be usable by non-strictly conforming code, it
should also include every extended type, and not just the ones that can
be brought into your code through the C++ standard library. That's
inherently unportable.

Are we having fun yet?

> Now if I want to allocate a buffer able to hold a class T, I make an
> union containing UAB and char[sizeof(T)].
>
> The question is: just how portable this is? I'm not interested in "it
> works with compiler X on OS Y". I need true universal portability.

It isn't universally portable. That's why many people have asked for a
maxalign_t.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]