[comp.lang.c] lint on malloc calls

jgb@linus.UUCP (Jonathan G. Bressel) (09/09/88)

What is the best way of using malloc to get a pointer to a structure?
I am using the line below:

	nextentry = (entry *) malloc(sizeof(entry));

where nextentry is defined as

	entry *nextentry;

Running lint -bach yields:

	phone.c(61): warning: illegal pointer combination
	phone.c(61): warning: possible pointer alignment problem

What am I doing wrong?  Doesn't K+R suggest this on pp. 133-134 (at
the end of section 6.5)?

Thanks.
-- 
Jonathan G. Bressel					The MITRE Corporation
							MS E095, POB 208,
ARPA:   linus!jgb@mitre-bedford                   	Bedford, MA  01730
UUCP:   ...{decvax,utzoo,philabs,genrad}!linus!jgb	(617) 271-2794

gwyn@smoke.ARPA (Doug Gwyn ) (09/09/88)

In article <39617@linus.UUCP> jgb@linus.UUCP (Jonathan G. Bressel) writes:
>	nextentry = (entry *) malloc(sizeof(entry));

That's correct.

>	phone.c(61): warning: illegal pointer combination
>	phone.c(61): warning: possible pointer alignment problem

"lint" doesn't know that malloc() always returns a suitably-aligned pointer.
There really isn't any way to prevent these warnings (other than changing
the code that "lint" sees).

shankar@hpclscu.HP.COM (Shankar Unni) (09/10/88)

>
>	nextentry = (entry *) malloc(sizeof(entry));
>
>Running lint -bach yields:
>
>	phone.c(61): warning: illegal pointer combination
>	phone.c(61): warning: possible pointer alignment problem

Well, one can sort of understand lint's point of view (assuming a low-IQ
lint):

   Malloc returns a "char *" (presumably that's how you declared it)
   a "char *" can *THEORETICALLY* point to the middle of a word
	(even though we know that malloc always returns appropriately
	 aligned pointers)
   
   ergo, casting it to a struct pointer could *THEORETICALLY* cause
   an alignment problem (if the struct has an alignment >= 1 word)

   (The illegal combination message is just plain dumb...)

A possible workaround to pacify your lint:

Declare malloc as

   double *malloc();

--
Shankar.

P.S. I don't know what this would do on machines in which char *'s and
double *'s have different representations and in which malloc actually
returns a char * aligned to a double boundary (believe me, I know such a
machine). But if your machine doesn't have a terminal case of pointer-
representation-itis, the above should work...

greggy@infmx.UUCP (greg yachuk) (09/10/88)

In article <39617@linus.UUCP> jgb@linus.UUCP (Jonathan G. Bressel) writes:
>	nextentry = (entry *) malloc(sizeof(entry));
>
>Running lint -bach yields:
>
>	phone.c(61): warning: illegal pointer combination
>	phone.c(61): warning: possible pointer alignment problem

Most likely, you have a somewhat advanced lint that understands that
int's and pointers do not need to be the same size.  If you have no
previous definition for malloc, it defaults to returning an int.  Lint
might not be impressed when you try to cast this to a pointer.  If you
#include <alloc.h> (or whatever is appropriate for your compiler), this
complaint will likely go away.  Alternatively, you could code your own
definition:
	void *malloc(); or char *malloc();

>Thanks.
You're welcome (I hope this is correct!!??)

>-- 
>Jonathan G. Bressel					The MITRE Corporation
>							MS E095, POB 208,
>ARPA:   linus!jgb@mitre-bedford                   	Bedford, MA  01730
>UUCP:   ...{decvax,utzoo,philabs,genrad}!linus!jgb	(617) 271-2794


Greg Yachuk		Informix Software Inc., Menlo Park, CA	(415) 322-4100
{uunet,pyramid}!infmx!greggy		why yes, I DID choose that login myself

Yes, yes hammerheads; swimming, kissing; we are big and clever and we don't know
				anything!
God save hammerheads; keeping going; we are sleek and special, and we're sure of
				something

tps@chem.ucsd.edu (Tom Stockfisch) (09/11/88)

In article <660017@hpclscu.HP.COM> shankar@hpclscu.HP.COM (Shankar Unni) writes:
>>
>>	phone.c(61): warning: illegal pointer combination
>>	phone.c(61): warning: possible pointer alignment problem

>A possible workaround to pacify your lint:
>Declare malloc as
>   double *malloc();

This is most preverse.  The point of trying to pacify lint is to make your
code portable.  You are proposing turning portable code into
non-portable code to pacify lint.
-- 

|| Tom Stockfisch, UCSD Chemistry	tps@chem.ucsd.edu

brian@bradley.UUCP (09/11/88)

> /* Written  3:12 pm  Sep  8, 1988 by jgb@linus.UUCP */

	[ edited for brevity ]

> 
> 	entry *nextentry;
> 
> 	nextentry = (entry *) malloc(sizeof(entry));
> 
> Running lint -bach yields:
> 
> 	phone.c(61): warning: illegal pointer combination
> 	phone.c(61): warning: possible pointer alignment problem
> 
> What am I doing wrong?  Doesn't K+R suggest this on pp. 133-134 (at
> the end of section 6.5)?

  You probably didn't tell lint or cc what malloc() returns, so it
assumed int malloc()... The warning is given because you have done
an explicit cast of a pointer to an integer. Just add the following
line to either the top of your program or the top of your function:

extern char *malloc();

  Or, if you compiler supports void*

extern void *malloc();

...............................................................................

  When the going gets weird, the weird turn pro.

  Brian Michael Wendt       UUCP: {cepu,ihnp4,uiucdcs,noao}!bradley!brian
  Bradley University        ARPA: cepu!bradley!brian@seas.ucla.edu
  (309) 677-2230            ICBM: 40 40' N  89 34' W

gwyn@smoke.ARPA (Doug Gwyn ) (09/11/88)

In article <660017@hpclscu.HP.COM> shankar@hpclscu.HP.COM (Shankar Unni) writes:
>A possible workaround to pacify your lint:
>Declare malloc as
>   double *malloc();

"The cure is worse than the disease."

"lint" should REALLY scream about incorrectly declaring the type
of a C library function.

gandalf@csli.STANFORD.EDU (Juergen Wagner) (09/12/88)

In article <9900007@bradley> brian@bradley.UUCP writes:
>
>> /* Written  3:12 pm  Sep  8, 1988 by jgb@linus.UUCP */
...
>> 	entry *nextentry;
>>
>> 	nextentry = (entry *) malloc(sizeof(entry));
>> 
>> Running lint -bach yields:
>> 
>> 	phone.c(61): warning: illegal pointer combination
>> 	phone.c(61): warning: possible pointer alignment problem
...
>
>  You probably didn't tell lint or cc what malloc() returns, so it
>assumed int malloc()... The warning is given because you have done
>an explicit cast of a pointer to an integer. Just add the following
>line to either the top of your program or the top of your function:
>
>extern char *malloc();

That might well be. If you don't use the above declaration lint will 
complain. Yet, it should say that this is an "illegal combination of
pointer and integer", not what you read above.

>  Or, if you compiler supports void*
>
>extern void *malloc();
>

What is that supposed to do? Casting that to a (char *) I got a warning
because (void *) objects may not be byte-addressable.

Still, I think, all this doesn't account for one big problem: what do you
do if you have a program like

	cp = (char *) malloc(10*sizeof(char));
	sp = (short *) malloc(10*sizeof(short));
	dp = (double *) malloc(10*sizeof(double));

where malloc indeed returns values of different type. Assuming (double *)
fits them all isn't sufficient. This might break on a machine with different
representations for word and for byte pointers. I don't think, there is any
other way than to make lint happy by saying

# ifdef lint
extern char *malloc_char();
extern short *malloc_short();
extern double *malloc_double();
# else !lint
#   define malloc_char   malloc
#   define malloc_short  malloc
#   define malloc_double malloc
# endif lint

That's ugly but didn't come across any panacea for this problem. If other 
people have other suggestions, please let me know.

-- 
Juergen "Gandalf" Wagner,		   gandalf@csli.stanford.edu
Center for the Study of Language and Information (CSLI), Stanford CA

rsalz@bbn.com (Rich Salz) (09/12/88)

Juergen "Gandalf" Wagner, <gandalf@csli.stanford.edu>, asks how you
can make lint happy if one program has the following three lines:
	cp = (char *) malloc(10*sizeof(char));
	sp = (short *) malloc(10*sizeof(short));
	dp = (double *) malloc(10*sizeof(double));

He suggests this:
	#ifdef	lint
	extern char *malloc_char();
	extern short *malloc_short();
	extern double *malloc_double();
	#else	/* !lint */
	#   define malloc_char   malloc
	#   define malloc_short  malloc
	#   define malloc_double malloc
	#endif	/* lint */

On the systems I use, which are mostly BSD derivatives, lint will keep
quiet if it sees you casting a "worst-case" pointer into something not
so bad.  I you write your own wrapper around malloc (which is usually
a good idea anyway), you can get the lint natterings down to one line.

In system_header.h
	typedef int WORST_CASE;
	extern WORST_CASE *Mallocator();
in alloc.c
	#include "system_header.h"
	WORST_CASE *
	Mallocator(count)
	    int count;
	{
	    char *malloc();
	    WORST_CASE p;

	    if (p = (WORST_CASE *)malloc(count))
		return(p);
	    YelpAndDie();
	}

I remember this trick also working on Version7 lints.
It's been a long time since I've used SysV-
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.

bill@proxftl.UUCP (T. William Wells) (09/13/88)

In article <39617@linus.UUCP> jgb@linus.UUCP (Jonathan G. Bressel) writes:
: What is the best way of using malloc to get a pointer to a structure?
: I am using the line below:
:
:       nextentry = (entry *) malloc(sizeof(entry));
:
: where nextentry is defined as
:
:       entry *nextentry;
:
: Running lint -bach yields:
:
:       phone.c(61): warning: illegal pointer combination
:       phone.c(61): warning: possible pointer alignment problem
:
: What am I doing wrong?  Doesn't K+R suggest this on pp. 133-134 (at
: the end of section 6.5)?

You are using lint. :-)

This is a problem with every lint I have used.  Lint doesn't
understand that malloc returns a properly aligned pointer, so you
get the messages.

To shut lint up, you need to trick it a little.  Here is one way:
Place

#ifdef lint                     /* lint defines this symbol */
#define malloc(x) 0
#endif

somewhere so that every call to malloc can be overridden by the
macro.  You may want to put a #undef malloc in front of the
#define.

---
Bill
novavax!proxftl!bill

woerz@iaoobelix.UUCP (Dieter Woerz) (09/14/88)

In article <9900007@bradley> brian@bradley.UUCP writes:
>
>> /* Written  3:12 pm  Sep  8, 1988 by jgb@linus.UUCP */
>
>       [ edited for brevity ]
>
>>
>>      entry *nextentry;
>>
>>      nextentry = (entry *) malloc(sizeof(entry));
>>
>> Running lint -bach yields:
>>
>>      phone.c(61): warning: illegal pointer combination
>>      phone.c(61): warning: possible pointer alignment problem
>>
>> What am I doing wrong?  Doesn't K+R suggest this on pp. 133-134 (at
>> the end of section 6.5)?
>
>  You probably didn't tell lint or cc what malloc() returns, so it
>assumed int malloc()... The warning is given because you have done
>an explicit cast of a pointer to an integer. Just add the following
>line to either the top of your program or the top of your function:

This isn't the cause here, because, if you don't tell lint, that
malloc returns a char *, lint will complain with a message:

    warning: illegal combination for pointer and integer, op =

The cause is, that jgb@linus.UUCP asked lint with the a flag to (I
cite the lint manual on Ultrix V2.2, the one I've handy)

    Complain about casts which have questionable portability.

The problem is, that lint doesn't know, that malloc always returns a
best aligned pointer instead of (as char * normally can) a possibly
worst aligned one. This would be of "questionable portability" for
other systems.

>extern char *malloc();
>
>  Or, if you compiler supports void*
>
>extern void *malloc();

This would only help, if you lint library, where malloc is defined,
is changed too for malloc returning void *. But I think lint must be
changed for this one too, as lint must know that a void * will always
be aligned properly. I'm not sure, if the current lint's know this
definition.

------------------------------------------------------------------------------

Dieter Woerz
Fraunhofer Institut fuer Arbeitswirtschaft und Organisation
Abt. 453
Holzgartenstrasse 17
D-7000 Stuttgart 1
W-Germany

BITNET: iaoobel.uucp!woerz@unido.bitnet
UUCP:   ...{uunet!unido, pyramid}!iaoobel!woerz

rb@ist.CO.UK (News reading a/c for rb) (09/15/88)

From article <8472@smoke.ARPA>, by gwyn@smoke.ARPA (Doug Gwyn ):
> "lint" doesn't know that malloc() always returns a suitably-aligned pointer.
> There really isn't any way to prevent these warnings (other than changing
> the code that "lint" sees).

Or modify lint (like we did) so that you can say:

/*ALIGNED*/
extern char *malloc();

and lint then doesn't complain about the alignment of the
value malloc returns.

karl@haddock.ima.isc.com (Karl Heuer) (09/17/88)

In article <216@iaoobelix.UUCP> woerz@iaoobelix.UUCP (Dieter Woerz) writes:
>>	extern void *malloc();
>
>This would only help, if you lint library, where malloc is defined,
>is changed too for malloc returning void *. But I think lint must be
>changed for this one too, as lint must know that a void * will always
>be aligned properly. I'm not sure, if the current lint's know this
>definition.

Since in fact a (void *) pointer is *not* always properly aligned, it's not
clear that this would be an appropriate change to make anyway.  Better would
be to have some other way to specify that malloc() is a special case.  I've
suggested doing it with a lintpragma:
	/* ALIGNED */
	extern void *malloc();	/* or "char *", if pre-ANSI */

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

bill@proxftl.UUCP (T. William Wells) (09/18/88)

I don't see why this is being debated any longer.  I suggested
adding the following kludge to each file where malloc is used:

#ifdef lint
#define malloc(x) 0
#endif

to shut up lint; this will work because each use of malloc will
be changed from

	ptr = (type)malloc(size);

to

	ptr = (type)0;

If you don't like this because it doesn't type check the malloc
argument, you can do this instead:

#ifdef lint
void malloc_kludge(n) size_t n; { n = n; }
#define malloc(x) (malloc_kludge(x), 0)
#endif

Can we have an end to this?

---
Bill
novavax!proxftl!bill

sullivan@vsi.UUCP (Michael T Sullivan) (09/20/88)

In article <781@proxftl.UUCP>, bill@proxftl.UUCP (T. William Wells) writes:
> I don't see why this is being debated any longer.  I suggested
> adding the following kludge to each file where malloc is used:
> 
> #ifdef lint
> #define malloc(x) 0
> #endif

Sorry, I was on vacation and didn't get to participate in the early goings.
Actually, to be complete do this:

#ifdef lint
#define	malloc(x)	0
#else
extern char	*malloc();	/* or void* if that's what it is	*/
#endif

This eliminates the need for people to declare malloc in their programs,
which would look pretty silly if you just #define'd malloc to be 0:

extern char	*0;

-- 
Michael Sullivan				{uunet|attmail}!vsi!sullivan
V-Systems, Inc. Santa Ana, CA			sullivan@vsi.com
whump, whump, whump, whump, whump, whump, whump, whump, whump, whump, whump