[comp.lang.c] How do I keep pointers aligned?

sean@ms.uky.edu (Sean Casey) (10/10/89)

Lint tells me I have possible pointer alignment problems.

In one case, I'm allocating storage for a struct:

typedef struct Stuff {
	int stufflet;
	etc;
} STUFF;

s = (STUFF *) malloc((unsigned) sizeof(STUFF));

Now we all know malloc returns a (char *). What I'm wondering is why
lint would complain. Aren't all pointers the same size? Does lint think
that perhaps a four byte pointer might be copied to a two byte pointer
that is not aligned so that it can be interpreted as a 4BP?

Am I missing something here?

In another case, when using varargs and given the definitions:

(in /usr/include/varargs.h)
# define va_arg(list,mode) ((mode *)(list += sizeof(mode)))[-1]

char *strings[255];

while (strings[argno++] = va_arg(ap, char *));

Produces the same warning, even though it exactly matches the usage example
given in the manual page. It does work, by the way.

Can I assume that a compiler will take:

struct Bunga {
	blah;
	any number of weird blah;
	struct Bunga *next;
};

And insure that next is properly aligned? Can I assume malloc always returns
me a char * that is aligned so that the above always works?

I'm using this stuff in a teleconferencing system server that's been
running for several months now. As far as I can tell, there's only one
instance where pointer alignment may have actually caused a crash, and
I'm not really sure about that.

I'm curious to know if i need to worry about this stuff. If not, I'd like
to know why lint complains.

Thanks,

Sean
-- 
***  Sean Casey          sean@ms.uky.edu, sean@ukma.bitnet, ukma!sean
***  Copyright 1989 by Sean Casey. Only non-profit redistribution permitted.
***  ``So if you weight long enough, you'll get your packets, right?''

cjc@ulysses.homer.nj.att.com (Chris Calabrese) (10/10/89)

In article <12879@s.ms.uky.edu>, sean@ms.uky.edu (Sean Casey) writes:
> Lint tells me I have possible pointer alignment problems.
> 
> In one case, I'm allocating storage for a struct:
> 
> typedef struct Stuff {
> 	int stufflet;
> 	etc;
> } STUFF;
> 
> s = (STUFF *) malloc((unsigned) sizeof(STUFF));
> 
> Now we all know malloc returns a (char *). What I'm wondering is why
> lint would complain. Aren't all pointers the same size? Does lint think
> that perhaps a four byte pointer might be copied to a two byte pointer
> that is not aligned so that it can be interpreted as a 4BP?
> 
> [ further examples and comments deleted ]

No, all pointers are not created equal!

I worked for a while on a machine (no longer in production) which had
a custom mmu on a 68010 (this was back before the official Motorola
mmu's came out) which did all sorts of weird things with word aligned
pointers of different sizes and really made my head spin sometimes
(this was back when I was a freshman undergraduate before I
learned about lint -p).  Come to think of it, you can do the same
thing on Intel i[023]86 architectures.

Even on normal architecures, however, (char *) must be able to point
to every memory address, whereas (STUFF *) may only be able to point
to word aligned addresses (for efficiency's sake).  Malloc makes sure
that it only passes word alighed pointers, but lint doesn't know
that.  K&R [ANSI] C guarentees that (STUFF *)(char *)type_stuff
[(STUFF *)(void *)type_stuff] works, but not the other way
around.

Hopefully, every malloc implementation gets it right!
-- 
Name:			Christopher J. Calabrese
Brain loaned to:	AT&T Bell Laboratories, Murray Hill, NJ
att!ulysses!cjc		cjc@ulysses.att.com
Obligatory Quote:	``Anyone who would tell you that would also try and sell you the Brooklyn Bridge.''

cpcahil@virtech.UUCP (Conor P. Cahill) (10/10/89)

In article <12879@s.ms.uky.edu>, sean@ms.uky.edu (Sean Casey) writes:
> Lint tells me I have possible pointer alignment problems.

	[ sample deleted ]

> Now we all know malloc returns a (char *). What I'm wondering is why
> lint would complain. Aren't all pointers the same size? Does lint think

The message about pointer alignment has nothing to do with the size of 
the pointer itself.  It is telling you that it is possible that the 
character pointer (which usually can align down to a 1 byte boundry) may
not point to a correctly aligned address required to correctly
dereference the non-char pointer.

For example:

	char	  buffer[20];
	long	* l;

	memset(buffer,'\0',20);

	l = (long *) buffer;		
	printf("l = %d",*l);		/* this will *usually* work */

	l = (long *) &buffer[1];
	printf("l = %d",*l);		/* 50-50 chances of a core dump */
	

The reason for the core dump would be that the CPU requires that all long
words start on a longword boundry (multiple of 4).  Trying to de-reference
a longword from an odd address will cause core dumps on half of the systems.

The return from malloc() is guarenteed (by the documentation) to be properly
alligned for all data types, but as far as I know there is no way to tell 
lint this.  That is why you only get a warning.


-- 
+-----------------------------------------------------------------------+
| Conor P. Cahill     uunet!virtech!cpcahil      	703-430-9247	!
| Virtual Technologies Inc.,    P. O. Box 876,   Sterling, VA 22170     |
+-----------------------------------------------------------------------+

henry@utzoo.uucp (Henry Spencer) (10/10/89)

In article <12879@s.ms.uky.edu> sean@ms.uky.edu (Sean Casey) writes:
>Lint tells me I have possible pointer alignment problems.
>s = (STUFF *) malloc((unsigned) sizeof(STUFF));


The problem is that lint has no way of knowing that the `char *' returned
by malloc is sufficiently well-aligned for use as a `STUFF *'.  In fact,
it is -- that's part of the specs of malloc -- but lint doesn't know that.

In practice, "possible pointer alignment problem" just means "better look
twice to make sure this is right".  It doesn't mean "this is wrong".
-- 
A bit of tolerance is worth a  |     Henry Spencer at U of Toronto Zoology
megabyte of flaming.           | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

jeff@cjsa.WA.COM (Jeffery Small) (10/10/89)

henry@utzoo.uucp (Henry Spencer) writes:
>In article <12879@s.ms.uky.edu> sean@ms.uky.edu (Sean Casey) writes:
>>Lint tells me I have possible pointer alignment problems.
>>s = (STUFF *) malloc((unsigned) sizeof(STUFF));

>The problem is that lint has no way of knowing that the `char *' returned
>by malloc is sufficiently well-aligned for use as a `STUFF *'.  In fact,
>it is -- that's part of the specs of malloc -- but lint doesn't know that.
>In practice, "possible pointer alignment problem" just means "better look
>twice to make sure this is right".  It doesn't mean "this is wrong".

Something I have often wondered:

Is there a good reason why lint hasn't been modified to understand the
"specs" of malloc and eliminate these unnecessary warnings?  Does building
such knowledge into lint violate its design philosophy?
--
Jeffery Small    (206) 485-5596            uw-beaver!uw-nsr!uw-warp
C. Jeffery Small and Associates                                    !cjsa!jeff
19112 152nd Ave NE - Woodinville, WA  98072           uunet!nwnexus