Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Aliasing bug when casting char[] into char* ?

Reply
Thread Tools

Aliasing bug when casting char[] into char* ?

 
 
Xavier Roche
Guest
Posts: n/a
 
      02-06-2007
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 ?)

 
Reply With Quote
 
 
 
 
matevzb
Guest
Posts: n/a
 
      02-06-2007
On Feb 6, 10:17 pm, Xavier Roche <(E-Mail Removed)>
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

 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      02-06-2007
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.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Old Wolf
Guest
Posts: n/a
 
      02-06-2007
On Feb 7, 10:17 am, Xavier Roche <(E-Mail Removed)>
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).

 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      02-07-2007
Xavier Roche <(E-Mail Removed)> 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


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Up casting and down casting Sosuke C++ 2 12-20-2009 03:24 PM
Problem with depracated casting method (down casting) Wally Barnes C++ 3 11-20-2008 05:33 AM
Aliasing bug when casting char[] into char* ? Xavier Roche C Programming 1 02-07-2007 08:05 AM
Another question about inheritance (up-casting and down-casting) kevin Java 11 01-08-2005 07:11 PM
[BUG] Aliasing :lambda Florian Gross Ruby 2 02-29-2004 10:35 AM



Advertisments