[net.lang.c] Dumb question on dyn. mem. alloc

delbene@homxa.UUCP (K.DELBENE) (07/18/85)

I've got a dumb question on the dynamic allocation of memory to
structures in 'C' using the malloc() family.  It seems that no
matter how I declare the function calloc() or how I typecast in
the returned pointer, I get a warning from lint that I have
a "possible pointer alignment problem."  Since I'm writing a
simulation, with these structures coming and going in volume,
I have to use dynamic allocation.  My question is, what problems
am I going to run into and how can I fix them (or should I just 
ignore the the message)?

				Kurt D. Del Bene
				...!ihnp4!homxa!delbene

P.S.  Please be gentle. I know 'C' (2 yrs. experience, 10k+ lines),
      but not its nuances.

P.P.S. Anyone know of a GOOD (i.e. well written) book on 'C' (other
       than K&R, which I've read and digested relatively completely) that
       doesn't treat you like some weekend programmer with a business degree
       from Podunk U?

henry@utzoo.UUCP (Henry Spencer) (07/19/85)

> ...  It seems that no
> matter how I declare the function calloc() or how I typecast in
> the returned pointer, I get a warning from lint that I have
> a "possible pointer alignment problem." ...  what problems
> am I going to run into and how can I fix them (or should I just 
> ignore the the message)?

Ignore the messages.  Lint is saying "you are casting one kind of pointer
to another, and this is an area where portability problems can occur";
it doesn't know that malloc() and friends are a special case where this
sort of thing is guaranteed to be safe.  This particular message is
enough of a pain that the "lint" entry in the Makefile for any program
of mine that uses malloc() a lot tends to read something like:

	lint foo bar bletch | egrep -v 'possible pointer alignment'

One should do this sort of thing with fear and trepidation, but it is
unfortunately true that *real* lint problems are much easier to spot when
they aren't buried in a river of meaningless complaints about malloc().
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

chris@umcp-cs.UUCP (Chris Torek) (07/20/85)

Lint doesn't realize that malloc and calloc have been written such
that that "possible pointer alignment problem" never occurs.  The
thing to do is ignore the message (or teach lint how to say that
a function returns a ``very aligned'' pointer; someone once suggested
using /*ALIGNOK*/ similar to the way /*NOTREACHED*/ and /*ARGSUSED*/
tell lint not to complain).

Another alternative is to use code like this:

	struct foo *
	getfoo()
	{
		struct foo *p;

	#ifdef lint
		p = NULL;
	#else
		p = (struct foo *)malloc((unsigned)sizeof (struct foo));
		if (p == NULL)
			error(1, errno, "out of memory in getfoo");
		p->this = p->that = theotherthing;
	#endif
		return (p);
	}

since lint knows that ``p = 0'' is not assigning an unaligned pointer
to p.  Of course this loses the type checking in the rest of the
code.  (Sigh.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

gwyn@BRL.ARPA (VLD/VMB) (07/21/85)

Unless someone has patched your version of "lint" to handle malloc()
as a special case, there is no way to avoid warnings about possible
pointer alignment problems.  That is because casting from a (char *)
to a (foo *) is not possible in general.  Malloc() has been specially
designed to ensure that its returned (char *) IS properly aligned for
anything whatsoever.  "lint" does not normally know this.

By the way, I would discourage using calloc() unless you are allocating
an array of (char)s and want them to all be NUL bytes.  Since calloc()
cannot guess how you are intending to use the storage it allocates,
it is unable to fill it with the "right" type of 0 data.  You will
normally be better off using malloc() and initializing the storage
yourself.

There aren't many good books in C for the non-novice.  You might look
at Narain Gehani's "Advanced C: Food for the Educated Palate"
(Computer Science Press, 1985).

ksbszabo@watvlsi.UUCP (Kevin Szabo) (07/22/85)

>> ...  It seems that no
>> matter how I declare the function calloc() or how I typecast in
>> the returned pointer, I get a warning from lint that I have
>> a "possible pointer alignment problem." 

What options are you passing to LINT? If you are on a BSD system, don't
use the -c option.  If you are on sys3/sys5 use the -c option.

Henry Spencer says:
>Ignore the messages...
>...the "lint" entry in the Makefile for any program
>of mine that uses malloc() a lot tends to read something like:
>	lint foo bar bletch | egrep -v 'possible pointer alignment'

Actually, you can get LINT to do a little bit more checking for you,
and thereby find a few of those irritating little bugs where you
allocate a structure of the wrong size while casting it to the correct
pointer type.  I find that LINT generally believes a cast to a pointer
type, as long as you don't/do use the -c option (on a BSD/SYSIII system).
The -c option tells lint to complain (or not complain) about all 
non-portable pointer mismatches and questionable pointer casting.

You can then automatically allocate a structure and cast it
using a nice little macro:

#define ALLOC( x )	((x *) malloc( sizeof(x)))

and a companion:

#define FREE( x )	free((char *) ( x ))

The ALLOC macro behaves like pascal's "new( x )" builtin, and reduces the
chances of a typographical error such as:
	ptr_type1 = (ptr_type1) malloc( sizeof (type2));
We started using the macros after we spent two days searching for exactly
this type of error.  Argh.

			Kevin
-- 
Kevin Szabo' watmath!wateng!ksbszabo (U of W VLSI Group, Waterloo, Ont, Canada)

guy@sun.uucp (Guy Harris) (07/22/85)

> Lint doesn't realize that malloc and calloc have been written such
> that that "possible pointer alignment problem" never occurs.  The
> thing to do is ignore the message (or teach lint how to say that
> a function returns a ``very aligned'' pointer; someone once suggested
> using /*ALIGNOK*/ similar to the way /*NOTREACHED*/ and /*ARGSUSED*/
> tell lint not to complain).

Hopefully, pointers of the ANSI C type "void *" will be able to be assigned
to any other pointer type without any complaints, including complaints about
possible alignment problems.  This is, of course, a horribly large loophole,
but there may be some small hope that people won't abuse it and will always
write routines like "malloc" which return "void *" values to align the
object pointed to so that it can, indeed, be used to point to anything.

	Guy Harris

arnold@ucsfcgl.UUCP (Ken Arnold%CGL) (07/22/85)

In article <921@umcp-cs.UUCP> chris@umcp-cs.UUCP (Chris Torek) writes:
>Lint doesn't realize that malloc and calloc have been written such
>that that "possible pointer alignment problem" never occurs.  The
>thing to do is ignore the message (or teach lint how to say that
>a function returns a ``very aligned'' pointer; someone once suggested
>using /*ALIGNOK*/ similar to the way /*NOTREACHED*/ and /*ARGSUSED*/
>tell lint not to complain).

There is the (as far as I know unimplemented but) documented /*NOSTRICT*/.
This seems to have been added to handle this kind of case, but I have
never, on any version of lint I've used, seen it actually work.  This
WOULD be a good solution.
		Ken Arnold

mff@wuphys.UUCP (Swamp Thing) (07/22/85)

In article <921@umcp-cs.UUCP> chris@umcp-cs.UUCP (Chris Torek) writes:
>Lint doesn't realize that malloc and calloc have been written such
>that that "possible pointer alignment problem" never occurs.  The
>thing to do is ignore the message (or teach lint how to say that
>a function returns a ``very aligned'' pointer; someone once suggested
>using /*ALIGNOK*/ similar to the way /*NOTREACHED*/ and /*ARGSUSED*/
>tell lint not to complain).

It seems to me that the thing to do is change or eliminate malloc and calloc.
It seems like a small price to pay to satisfy the great and powerful LINT.
Hardly any change at all compared to creating an entire new variable type!



						Mark F. Flynn
						Department of Physics
						Washington University
						St. Louis, MO  63130
						ihnp4!wuphys!mff

"Into the void boys, into the void."

henry@utzoo.UUCP (Henry Spencer) (07/22/85)

> ...  I find that LINT generally believes a cast to a pointer
> type, as long as you don't/do use the -c option (on a BSD/SYSIII system).
> The -c option tells lint to complain (or not complain) about all 
> non-portable pointer mismatches and questionable pointer casting.

Sigh, not so on a V7, which is why I mentioned the "grep -v" approach.
The absence of -c does *not* tell the V7 lint to shut up about possible
alignment problems.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

tp@ndm20 (07/30/85)

>I just realised a major problem with (void *). On machines like the HP-1000
>a pointer to a byte and a pointer to a word don't have the same bit-pattern.

That is probably try of ANY machine which is addressed by some unit larger
than a byte. We use a Harris H series computer, which is word addresseable
(24-bit words, even), and a pointer to a char definately does NOT look like
a pointer to anything else. You have to cast them properly. I don't know about
void, as I haven't seen the ANSI C draft, but on the Harris, anything that 
returns a "generic" pointer must return a char pointer with word alignment.
It then MUST be cast to the appropriate type (which reformats the pointer
properly). A pointer to void would presumably have to use the same approach.