Boost logo

Boost :

From: Bill Wade (bill.wade_at_[hidden])
Date: 2000-08-24 08:11:37


> -----Original Message-----
> From: David Abrahams [mailto:abrahams_at_[hidden]]

> The goal is to portably sub-allocate a POD struct from larger blocks
> obtained from malloc() without wasting space or invoking
> undefined behavior.
> The POD struct ends with a variable-length array. Here is an
> example of what
> the struct looks like:
>
> struct Rule
> {
> unsigned long cost;
> const void* action;
> const char* symbols[1]; // actually a variable-length array
> };
>
> [ discussion trimmed ]
> but remember I want a *portable* solution.

You can certainly find an alignment that "works" (although I don't believe
there is a portable way to find the minimum alignment that works). However
even if you do so the code using Report is not strictly portable. This is
the (in)famous "struct hack." Conforming compilers may perform bounds
checking on arrays and pointers.

  myrule.symbols[2];

and even

  myrule.symbols+2;

invoke undefined behavior even if the memory is available and properly
aligned.

For instance an optimizing compiler "knows" that
  myrule.symbols[i] = "hello";
is undefined if 'i' is not zero. As a result, the compiler is allowed to
assume 'i' is zero and generate faster and smaller code that does not do the
pointer math.

In range-checking implementations that I've seen, the range-checking gets
turned off when the pointer is involved in a cast:

struct Rule
{
    unsigned long cost;
    const void* action;
    const char** symbols(){ return (const char**) (&action+1); }
};

HTH, YMMV


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk