By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,172 Members | 1,092 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,172 IT Pros & Developers. It's quick & easy.

Aliasing bug when casting char[] into char* ?

P: n/a
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 ?)

Feb 6 '07 #1
Share this Question
Share on Google+
4 Replies


P: n/a
On Feb 6, 10:17 pm, Xavier Roche <xro...@free.fr.NOSPAM.invalid>
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

Feb 6 '07 #2

P: n/a
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.

--
Er*********@sun.com
Feb 6 '07 #3

P: n/a
On Feb 7, 10:17 am, Xavier Roche <xro...@free.fr.NOSPAM.invalid>
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).

Feb 6 '07 #4

P: n/a
Xavier Roche <xro...@free.fr.NOSPAM.invalidwrote:
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.hheader 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
Feb 7 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.