Aliasing bug when casting char[] into char* ?

Discussion in 'C Programming' started by Xavier Roche, Feb 6, 2007.

  1. Xavier Roche

    Xavier Roche Guest

    Hi folks,

    I have a probably rather silly question: is casting a char array in a
    char* a potential source of aliasing bug ?

    Example: a fonction returning a buffer taken in a circular buffer

    typedef struct foo_t foo_t;
    struct foo_t {
    int index;
    char buff[16][8192];
    };

    static char* getBuff(foo_t *s) {
    s->index = ( s->index + 1 ) % 16;
    printf("returning s->buff[%d] == %p\n",
    s->index, s->buff[s->index]);
    return s->buff[s->index];
    }

    void test(char *a, char *b) {
    printf("got pointers: %p %p\n", a, b);
    }

    int main(void) {
    foo_t s = { 0 };
    test(getBuff(&s), getBuff(&s));
    return 0;
    }

    The problem is that on Visual C++ 2003, the two returned pointers are
    identical when optimizing (!)

    Tested with Visual C++ 2003, release mode (optimized)

    returning s->buff[1] == 00111F5C
    returning s->buff[2] == 00113F5C
    got pointers: 00113F5C 00113F5C

    Tested with gcc 3.3.4, optimized (O4):

    returning s->buff[1] == 0xfffde008
    returning s->buff[2] == 0xfffe0008
    got pointers: 0xfffde008 0xfffe0008

    Is the bug inside this code ? (or inside the compiler ?)
     
    Xavier Roche, Feb 6, 2007
    #1
    1. Advertising

  2. Xavier Roche

    matevzb Guest

    On Feb 6, 10:17 pm, Xavier Roche <>
    wrote:
    > Hi folks,
    >
    > I have a probably rather silly question: is casting a char array in a
    > char* a potential source of aliasing bug ?

    I'm not sure what you mean, I don't see any casts in your code.
    >
    > Example: a fonction returning a buffer taken in a circular buffer

    #include <stdio.h>
    >
    > typedef struct foo_t foo_t;
    > struct foo_t {
    > int index;
    > char buff[16][8192];
    > };
    >
    > static char* getBuff(foo_t *s) {
    > s->index = ( s->index + 1 ) % 16;
    > printf("returning s->buff[%d] == %p\n",
    > s->index, s->buff[s->index]);

    When using %p, the argument must be a pointer to void, so you need an
    explicit cast here:
    (void *)s->buff[s->index]
    > return s->buff[s->index];
    > }
    >
    > void test(char *a, char *b) {
    > printf("got pointers: %p %p\n", a, b);

    Same as above, a missing (void *) cast.
    > }
    >
    > int main(void) {
    > foo_t s = { 0 };
    > test(getBuff(&s), getBuff(&s));

    The order of evaluation is unspecified for function arguments, so
    don't use it like this. Better:
    char *p1 = getBuff (&s);
    char *p2 = getBuff (&s);
    test (p1, p2);
    > return 0;
    > }
    >
    > The problem is that on Visual C++ 2003, the two returned pointers are
    > identical when optimizing (!)

    I'm probably missing something here, but someone else will point out
    the (obvious) problem. I suggest you fix the above problems first and
    see if it helps.
    <snip>
    --
    WYCIWYG - what you C is what you get
     
    matevzb, Feb 6, 2007
    #2
    1. Advertising

  3. Xavier Roche

    Eric Sosman Guest

    Xavier Roche wrote On 02/06/07 16:17,:
    > Hi folks,
    >
    > I have a probably rather silly question: is casting a char array in a
    > char* a potential source of aliasing bug ?
    >
    > Example: a fonction returning a buffer taken in a circular buffer
    >
    > typedef struct foo_t foo_t;
    > struct foo_t {
    > int index;
    > char buff[16][8192];
    > };
    >
    > static char* getBuff(foo_t *s) {
    > s->index = ( s->index + 1 ) % 16;
    > printf("returning s->buff[%d] == %p\n",
    > s->index, s->buff[s->index]);
    > return s->buff[s->index];
    > }
    >
    > void test(char *a, char *b) {
    > printf("got pointers: %p %p\n", a, b);
    > }
    >
    > int main(void) {
    > foo_t s = { 0 };
    > test(getBuff(&s), getBuff(&s));
    > return 0;
    > }
    >
    > The problem is that on Visual C++ 2003, the two returned pointers are
    > identical when optimizing (!)
    >
    > Tested with Visual C++ 2003, release mode (optimized)
    >
    > returning s->buff[1] == 00111F5C
    > returning s->buff[2] == 00113F5C
    > got pointers: 00113F5C 00113F5C
    >
    > Tested with gcc 3.3.4, optimized (O4):
    >
    > returning s->buff[1] == 0xfffde008
    > returning s->buff[2] == 0xfffe0008
    > got pointers: 0xfffde008 0xfffe0008
    >
    > Is the bug inside this code ? (or inside the compiler ?)


    It looks like the compiler is at fault (or else I've
    missed something). The two pointers could appear in either
    order in the "got pointers" line because the compiler can
    choose to evaluate the `a' argument either before or after
    the `b' argument, but no matter which order it chooses the
    two printed values should be different.

    --
     
    Eric Sosman, Feb 6, 2007
    #3
  4. Xavier Roche

    Old Wolf Guest

    On Feb 7, 10:17 am, Xavier Roche <>
    wrote:
    > static char* getBuff(foo_t *s) {
    > s->index = ( s->index + 1 ) % 16;
    > printf("returning s->buff[%d] == %p\n",
    > s->index, s->buff[s->index]);
    > return s->buff[s->index];
    > }
    >
    > void test(char *a, char *b) {
    > printf("got pointers: %p %p\n", a, b);
    > }
    >
    > int main(void) {
    > foo_t s = { 0 };
    > test(getBuff(&s), getBuff(&s));
    > return 0;
    > }
    >
    > Tested with Visual C++ 2003, release mode (optimized)
    >
    > returning s->buff[1] == 00111F5C
    > returning s->buff[2] == 00113F5C
    > got pointers: 00113F5C 00113F5C


    Has to be a compiler bug. I wonder if you could inspect the
    assembly code generated, and see what it is actually
    doing. Does it make any difference if you remove the
    'static' keyword? (Not that it should, but perhaps the
    compiler is getting confused).

    Also, check that the compiler is in ISO C++ compliance
    mode (if it has one!); some compilers have optimization
    switches that violate the standard (ie. make assumptions
    that are not guaranteed).
     
    Old Wolf, Feb 6, 2007
    #4
  5. Xavier Roche <> wrote:
    > Hi folks,
    >
    > I have a probably rather silly question: is casting a char array in a
    > char* a potential source of aliasing bug ?
    >
    > Example: a fonction returning a buffer taken in a circular buffer


    I don't see a #include <stdio.h> header anywhere.

    If that's missing then you don't have a prototype for the variadic
    function
    printf. Which means the behaviour is undefined.

    > typedef struct foo_t foo_t;
    > struct foo_t {
    > int index;
    > char buff[16][8192];


    This means the struct is at least 131072 bytes. This exceeds the
    minimum
    required implementation limit of 32767 bytes of an object in C90.

    What happens if you make the buffers smaller...?

    char buff[16][16];

    I suggest you allocate the buffers dynamically.

    > };
    >
    > static char* getBuff(foo_t *s) {
    > s->index = ( s->index + 1 ) % 16;
    > printf("returning s->buff[%d] == %p\n",
    > s->index, s->buff[s->index]);


    Although char * and void * are required to have the same
    representation,
    you're best of converting the second parameter to void * as required
    by
    %p.

    > return s->buff[s->index];
    >
    > }
    >
    > void test(char *a, char *b) {
    > printf("got pointers: %p %p\n", a, b);


    Ditto.

    >
    > }
    >
    > int main(void) {
    > foo_t s = { 0 };
    > test(getBuff(&s), getBuff(&s));
    > return 0;
    > }
    >
    > The problem is that on Visual C++ 2003, the two returned pointers are
    > identical when optimizing (!)
    >
    > Tested with Visual C++ 2003, release mode (optimized)
    >
    > returning s->buff[1] == 00111F5C
    > returning s->buff[2] == 00113F5C
    > got pointers: 00113F5C 00113F5C
    >
    > Tested with gcc 3.3.4, optimized (O4):
    >
    > returning s->buff[1] == 0xfffde008
    > returning s->buff[2] == 0xfffe0008
    > got pointers: 0xfffde008 0xfffe0008


    --
    Peter
     
    Peter Nilsson, Feb 7, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. lovecreatesbeauty
    Replies:
    1
    Views:
    1,149
    Ian Collins
    May 9, 2006
  2. Xavier Roche

    Aliasing bug when casting char[] into char* ?

    Xavier Roche, Feb 6, 2007, in forum: C Programming
    Replies:
    1
    Views:
    352
    Xavier Roche
    Feb 7, 2007
  3. Paul Brettschneider

    char and strict aliasing

    Paul Brettschneider, Jul 17, 2008, in forum: C++
    Replies:
    4
    Views:
    454
    James Kanze
    Jul 18, 2008
  4. Florian Gross

    [BUG] Aliasing :lambda

    Florian Gross, Feb 28, 2004, in forum: Ruby
    Replies:
    2
    Views:
    144
  5. Xavier Roche
    Replies:
    3
    Views:
    150
    James Kuyper
    Mar 25, 2014
Loading...

Share This Page