_Region_Get and strict aliasing

Sergei Organov osv at javad.com
Wed Dec 20 11:36:20 UTC 2006


Steven Johnson <sjohnson at sakuraindustries.com> writes:
> Well in that case, isn't the following in RTEMS broken RE strict
> aliasing (Which the _Region_Get code pointed me to):
>
> chain.h states:
>
> /**
> *  @struct Chain_Node_struct
> *
> *  This is used to manage each element (node) which is placed
> *  on a chain.
> *
> *  @note Typically, a more complicated structure will use the
> *        chain package.  The more complicated structure will
> *        include a chain node as the first element in its
> *        control structure.  It will then call the chain package
> *        with a pointer to that node element.  The node pointer
> *        and the higher level structure start at the same address
> *        so the user can cast the pointers back and forth.
> *
> */
> struct Chain_Node_struct {
>  /** This points to the node after to this one on this chain. */
>  Chain_Node *next;
>  /** This points to the node immediate prior to this one on this chain. */
>  Chain_Node *previous;
> };
>
> so the whole premise of the chain code is that a cast will be
> performed from some "more complicated" structure, that starts with a
> Chain_Node structure as its first element, down to a
> Chain_Node_Structure, so the generic chain code can be used on it (as
> the chain code doesn't care about what is held by the rest of the
> structure).

Well, suppose we have:

typedef struct {
  Chain_Node node;
  int a;
} MyStruct;

MyStruct s;
MyStruct *ps = &s;
Chain_Node *pn1 = &s.node;
Chain_Node *pn2 = (Chain_Node)&s;

void foo()
{
  ps->node.next = something;
  pn1->next = something_else;
  pn2->next = something_yet_another;
}

Does any of the above lines in foo() violate strict aliasing rules?

Obviously, the first and the second one don't. So those that remains in
question is the third line, but I fail to see any difference between the
third and the second lines, as in both cases the object 's.node' is
accessed through the same lvalue of the same effective type. I.e., as
pn2 has exactly the same type and points to exactly the same place in
memory as pn1, it seems that the third line should also be OK. Though
it's beyond my current understanding of the standard to either prove it,
or to prove otherwise.  Anybody?

What is interesting, in addition to the above, due to one of exceptions
stated in the standard, in particular,

  An object shall have its stored value accessed only by an lvalue
  expression that has one of the following types:

  [...]

  - an aggregate or union type that includes one of the aforementioned types among its
    members (including, recursively, a member of a subaggregate or contained union)

the following code doesn't seem to violate aliasing rules:

Chain_Node node;
MyStruct *ps = (MyStruct*)&node;

void boo()
{
  ps->node.next = NULL;
}

Well, if this code doesn't violate aliasing, then IMHO pn2->next line in
the foo() even less likely to violate them.

Note that we even didn't start to discuss the description of the
"effective type" in the standard:

  The effective type of an object for an access to its stored value is the
  declared type of the object, if any.(73) If a value is stored into an
  object having no declared type through an lvalue having a type that is
  not a character type, then the type of the lvalue becomes the effective
  type of the object for that access and for subsequent accesses that do
  not modify the stored value. If a value is copied into an object having
  no declared type using memcpy or memmove, or is copied as an array of
  character type, then the effective type of the modified object for that
  access and for subsequent accesses that do not modify the value is the
  effective type of the object from which the value is copied, if it has
  one. For all other accesses to an object having no declared type, the
  effective type of the object is simply the type of the lvalue used for
  the access.
  
  (73) Allocated objects have no declared type.

Can anybody figure out if it's possible to write custom allocators
similar to malloc()/free() without violating C99 aliasing rules? For me
it seems that even if I come up with a way to return a pointer to an
object without declared type from an analog of malloc() (e.g., I first
allocate a memory range by system malloc()), my free() won't be able to
get rid of the effective type that has been assigned to the object
during its use in the calling code :(

In particular, it could be the case that all RTEMS code that uses RTEMS
heap allocator, and most of the code does, violates aliasing rules :(

-- Sergei.



More information about the users mailing list