SUMMARY: Bug in Sun compiler?

Brian Sherwood (sherwood@alux4.micro.lucent.com)
Thu, 19 Feb 1998 09:36:35 -0500 (EST)

The bug was in my program, not the sun compiler.

I planed on malloc'ing the memory after I got other parts working
correctly, and was just using a char array for debugging for now.

I totally forgot about alignment issues (programming in perl too long :) )

My char array was not aligned properly. I will switch to malloc.

(I guess I just got lucky with the GNU compiler)

Thank you for all the replies.

Brian

==========================================================

>From parpae@jgbdev.fi.gs.com Thu Feb 19 09:19:27 1998
Date: Thu, 19 Feb 98 13:34:25 JST
From: Emy Parparita <parpae@jgbdev.fi.gs.com>
To: Brian Sherwood <sherwood@aluxpo>
Subject: Re: Bug in Sun compiler?

your printf assumes long alignment (multiple of 4 bytes) for the data pointed
by `ptr', which is not necessarily the case since `data' is array of chars.
try to inforce the alignment by a union

int main()
{
union {
char data[255];
long dummy;
} a;

void *ptr;

a.data[0] = 0x0;
a.data[1] = 0x0;
a.data[2] = 0x3;
a.data[3] = 0xd0;
a.data[4] = 0x0;

ptr = a.data;
printf ("size = %ld\n", *((long *)ptr) );

}

or use malloc/alloca (which always returns aligned data).

int main()
{

char *data;
void *ptr;

if ((data = (char*)malloc(256)) == NULL) {
fprintf(stderr, "malloc(): not enough memory\n");
exit(1);
}
data[0] = 0x0;
data[1] = 0x0;
data[2] = 0x3;
data[3] = 0xd0;
data[4] = 0x0;

ptr = data;
printf ("size = %ld\n", *((long *)ptr) );

}

i hope it helps,
emy

On Feb 18, 10:39pm, Brian Sherwood wrote:
> Subject: Bug in Sun compiler?
>
> Hello,
>
> I am running solaris 2.5.1 on a 4000 with Sparc Compiler 3.0.1
>
> I am reading in some data from a socket, the first 4 bytes are a long
> integer, followed by a char, etc...
>
> I read it all into a char array called data, and plan on using a void
> (or char) pointer to step through the data, casting the pointer as needed.
>
> My code compiles, but gives a "Bus error (core dumped)" error when I try
> to run the code produced by the sun compiler. Everthing works fine with
> gcc. I have simplified the problem to the block of code below, which
> still produces the error.
>
> Can the sun compiler not cast a pointer, or am I missing something
> stupid? Is the GNU compiler better than Sun's?
>
> Thanks for any help.
>
> Brian
>
> ===================================
> #include <stdio.h>
>
> int main()
> {
> char data[255];
> void *ptr;
>
> data[0] = 0x0;
> data[1] = 0x0;
> data[2] = 0x3;
> data[3] = 0xd0;
> data[4] = 0x0;
>
> ptr = data;
> printf ("size = %ld\n", *((long *)ptr) );
>
> }
>
>
> =========================================================================
> Brian Sherwood e-mail: bsherwood@lucent.com
> Systems Administrator e-mail: sherwood@aluxpo.micro.lucent.com
> IBM Global Services Voice: 610-712-6336
>
>
>
>-- End of excerpt from Brian Sherwood

-- 
+-------+  ----------------------------------------------------------
|Goldman|  Emy Parparita, FI-SA           Voice:  +81-3-5563-7574
|Sachs  |  Goldman Sachs (Japan) Limited  Beeper: +81-3-6124-2102
|       |  1-12-32 Akasaka Ark Mori Bldg  Fax:    +81-3-3589-5880  
|       |  Minato-ku,  Tokyo  Japan  107  mailto:emy.parparita@gs.com
+-------+  ----------------------------------------------------------

>From itc1@scigen.co.uk Thu Feb 19 09:19:46 1998 Date: Thu, 19 Feb 1998 08:40:55 GMT From: Ian TCollins <itc1@scigen.co.uk> To: sherwood@aluxpo Subject: Re: Bug in Sun compiler?

You could be seeing an alignment problem, try:

Print %p of ptr, if it is not divisible by 4, that's the problem.

Compile with -mt as an option, this sorts this kind of problem.

Ian

>From casper@holland.Sun.COM Thu Feb 19 09:19:52 1998 Date: Thu, 19 Feb 1998 09:30:35 +0100 From: Casper Dik <casper@holland.Sun.COM> To: Brian Sherwood <sherwood@aluxpo> Subject: Re: Bug in Sun compiler?

>Can the sun compiler not cast a pointer, or am I missing something >stupid? Is the GNU compiler better than Sun's?

You code is broken and you got lucky with gcc.

> char data[255]; > void *ptr;

> ptr = data; > printf ("size = %ld\n", *((long *)ptr) );

You have no idea how data would be aligned; gcc apparently aligns it on a 4 byte boundary, Sun's compiler aligns it on a odd boundary (presumably because it uses stack ptr - 255).

When converting pointers from one type to another, you must make sure that the alignment requirements are met.

In this case, your only option is:

long dl;

memcpy((void*)&dl, data, sizeof(long))

Casper

>From itc1@scigen.co.uk Thu Feb 19 09:20:07 1998 Date: Thu, 19 Feb 1998 08:45:44 GMT From: Ian TCollins <itc1@scigen.co.uk> To: sherwood@aluxpo Subject: Re: Bug in Sun compiler?

Oops, I should have said use -misalign!

This does indeed, sort the problem:

cc -misalign -o bug bug.c bug ptr = effff3fd size = 976

Ian

>From kevin@uniq.com.au Thu Feb 19 09:21:43 1998 Date: Thu, 19 Feb 1998 19:58:37 EST From: "Kevin.Sheehan@uniq.com.au" <kevin@uniq.com.au> To: Brian Sherwood <sherwood@aluxpo> Subject: Re: Bug in Sun compiler?

[ Regarding "Bug in Sun compiler?", sherwood@alux4.micro.lucent.com writes on Feb 18: ]

> I am reading in some data from a socket, the first 4 bytes are a long > integer, followed by a char, etc... > > I read it all into a char array called data, and plan on using a void > (or char) pointer to step through the data, casting the pointer as needed. > > My code compiles, but gives a "Bus error (core dumped)" error when I try > to run the code produced by the sun compiler. Everthing works fine with > gcc. I have simplified the problem to the block of code below, which > still produces the error.

I suspect if you truss it or look at the core dump you will indeed see an alignment error as the cause of the bus error. > > Can the sun compiler not cast a pointer, or am I missing something > stupid? Is the GNU compiler better than Sun's?

The compiler can cast fine, but you haven't given it enough information with regards to alignment. Strictly speaking, this is not correct C and you are getting lucky with gcc.

Casting upwards in alignment should generate a warning - char data[255] has only char alignment restriction, and you are using long with a cast.

The right way (and what works on either :-) is to declare a structure, or to declare it as an array of longs and then cast a (char *) to some part of it. That gives any compiler enough info to do the right thing, and it means you can derefrence a struct instead of casting or dereference a long that is known to be aligned.

Structure is my preferred method, as it documents what you expect to see in the protocol.

l & h, kev > > Thanks for any help. > > Brian > > =================================== > #include <stdio.h> > > int main() > { > char data[255]; > void *ptr; > > data[0] = 0x0; > data[1] = 0x0; > data[2] = 0x3; > data[3] = 0xd0; > data[4] = 0x0; > > ptr = data; > printf ("size = %ld\n", *((long *)ptr) ); > > } > > > ========================================================================= > Brian Sherwood e-mail: bsherwood@lucent.com > Systems Administrator e-mail: sherwood@aluxpo.micro.lucent.com > IBM Global Services Voice: 610-712-6336 > > >

>From alex@pc-alex.srce.hr Thu Feb 19 09:22:07 1998 Date: 19 Feb 1998 10:44:53 +0100 From: "Aleksandar Milivojevic <alex@srce.hr>" <alex@pc-alex.srce.hr> To: Brian Sherwood <sherwood@aluxpo> Subject: Re: Bug in Sun compiler?

[The following text is in the "ISO-8859-2" character set] [Your display is set for the "US-ASCII" character set] [Some characters may be displayed incorrectly]

Hi there,

No, it is not a bug in compiler. It is bug in you program. You made three assumptions. You had luck with two, but was without luck with other.

Integers on sparc procesor must start on even address. If you look with debugger, you'll see that compiler puts data array on odd address:

(dbx) print &data &data = 0xeffffb1d

and that is perfectly legal for chars on sparc procesor (since sparc can read single byte from odd address), but not for int or long (they must start on even address) and it (procesor) generates "Bus Error" exception, OS catches it and delivers SIGBUS signal ("Bus Error") to proces.

It seems that gcc will place data array on even address (well, at lest for this particular example) and that's way your program will "work" if compiled with it. But if you run it on say sparc and i386 it will give different results becose one is big endian and the other is little endian.

If you don't care about portability and need code that will work only on sparc, you can do something like this:

char *data; long ptr;

data = (char *) &ptr;

data[0] = 0x0; data[1] = 0x0; data[2] = 0x3; data[3] = 0xd0;

printf ("size = %ld\n", ptr );

But this is dirty, and I don't recomend it.

The third assumption was that long is 32 bit. On Solaris this is correct (at leas for now). But on Digital UNIX for example, long is 64 bits.

Brian Sherwood (sherwood@alux4.micro.lucent.com) wrote: > Hello, > > I am running solaris 2.5.1 on a 4000 with Sparc Compiler 3.0.1 > > I am reading in some data from a socket, the first 4 bytes are a long > integer, followed by a char, etc... > > I read it all into a char array called data, and plan on using a void > (or char) pointer to step through the data, casting the pointer as needed. > > My code compiles, but gives a "Bus error (core dumped)" error when I try > to run the code produced by the sun compiler. Everthing works fine with > gcc. I have simplified the problem to the block of code below, which > still produces the error. > > Can the sun compiler not cast a pointer, or am I missing something > stupid? Is the GNU compiler better than Sun's? > > Thanks for any help. > > Brian > > =================================== > #include <stdio.h> > > int main() > { > char data[255]; > void *ptr; > > data[0] = 0x0; > data[1] = 0x0; > data[2] = 0x3; > data[3] = 0xd0; > data[4] = 0x0; > > ptr = data; > printf ("size = %ld\n", *((long *)ptr) ); > > } > > > ========================================================================= > Brian Sherwood e-mail: bsherwood@lucent.com > Systems Administrator e-mail: sherwood@aluxpo.micro.lucent.com > IBM Global Services Voice: 610-712-6336 > > > >

-- 
Aleksandar Milivojeviæ   |  alex@srce.hr  |   http://jagor.srce.hr/~alex/
                  Opinions expressed herein are my own.
================================ooooO=Ooooo==============================
  Real Users never know what they want, but they always know when your
                       program doesn't deliver it.

>From avarvit@cc.ece.ntua.gr Thu Feb 19 09:23:09 1998 Date: Thu, 19 Feb 1998 14:27:46 +0200 (EET) From: "Aggelos P. Varvitsiotis" <avarvit@cc.ece.ntua.gr> To: sherwood@aluxpo Subject: Re: Bug in Sun compiler?

> Hello, > > I am running solaris 2.5.1 on a 4000 with Sparc Compiler 3.0.1 > > I am reading in some data from a socket, the first 4 bytes are a long > integer, followed by a char, etc... > > I read it all into a char array called data, and plan on using a void > (or char) pointer to step through the data, casting the pointer as needed. > > My code compiles, but gives a "Bus error (core dumped)" error when I try > to run the code produced by the sun compiler. Everthing works fine with > gcc. I have simplified the problem to the block of code below, which > still produces the error. > > Can the sun compiler not cast a pointer, or am I missing something > stupid? Is the GNU compiler better than Sun's? > > Thanks for any help. > > Brian > > =================================== > #include <stdio.h> > > int main() > { > char data[255]; > void *ptr; > > data[0] = 0x0; > data[1] = 0x0; > data[2] = 0x3; > data[3] = 0xd0; > data[4] = 0x0; > > ptr = data; > printf ("size = %ld\n", *((long *)ptr) ); > > }

Yes, you *are* missing something. It is called "alignment" and translates into the fact that, when you program in sparc arch, a long must be (32-bit-)word-aligned. In other words, if before your printf statement (((unsigned long) ptr) % 4) is non-zero, you 'll get a bus error.

How to fix that: declare your data as unsigned long data [ 256 / sizeof (unsigned long)]; so the compiler gets an idea on how you mean to access your data. You 'll be still unable though to address non-word-aligned integers. That is, something like

unsigned long data [ 256 / sizeof (unsigned long)]; char *ptr = (char *) &data[0]; ptr ++; printf ("size=%ld\n", *((long *)ptr));

will still give you a bus error.

a.varvitsiotis@iccs.ntua.gr A.Varvitsiotis ICCS Computer Center National Technical University of Athens

>From blackman@voicenet.com Thu Feb 19 09:23:35 1998 Date: 19 Feb 1998 13:15:46 -0000 From: blackman@voicenet.com To: sherwood@aluxpo Subject: Re: Bug in Sun compiler?

Addresses of integers on the sparc must be divisible by 4. There is no guarantee that your 'char data[255]' array is allocated this way.

========================================================================= Brian Sherwood e-mail: bsherwood@lucent.com Systems Administrator e-mail: sherwood@aluxpo.micro.lucent.com IBM Global Services Voice: 610-712-6336