[comp.lang.c] Yet Another Lint Foul-up

vevea@paideia.uchicago.edu (Jack L. Vevea) (01/06/89)

	I've passively watched the discussion of lint's problems with
  exit(0) from main(), and find myself wondering why it matters.  I use
  lint to check my code, but I've gotten into the habit of automatically
  ignoring certain output, including 'warning:  main() returns a random
  value to the invocation environment.'  Being primarily a psychometrician,
  and not a professional C (or any other language) programmer, I find myself
  wondering if some of you out there are working under conditions in which
  some higher authority requires you to produce a clean lint run as 
  evidence of good coding.  Otherwise, it would seem to me that any
  concern with the message would be evidence of your being a slave to
  lint; why else be concerned when you _know_ that the warning is
  inconsequential?

duane@cg-atla.UUCP (Andrew Duane) (01/06/89)

In article <1298@tank.uchicago.edu>, vevea@paideia.uchicago.edu (Jack L. Vevea) writes:
> 
> 	I've passively watched the discussion of lint's problems with
>   exit(0) from main(), and find myself wondering why it matters.  I use
>   lint to check my code, but I've gotten into the habit of automatically
>   ignoring certain output, including 'warning:  main() returns a random
>   value to the invocation environment.'  Being primarily a psychometrician,
>   and not a professional C (or any other language) programmer, I find myself
>   wondering if some of you out there are working under conditions in which
>   some higher authority requires you to produce a clean lint run as 
>   evidence of good coding.  Otherwise, it would seem to me that any
>   concern with the message would be evidence of your being a slave to
>   lint; why else be concerned when you _know_ that the warning is
>   inconsequential?

But sometimes the exit value of a program is important. I
regularly use many shell scripts that require correct (and
explicit) exit codes. Also, the system() library routine
returns (in a contorted fashion) the exit code of the program;
thus other programs can depend on it. GREP is a good example of
this.

If "main() returns a random value to the invocation environment"
then these scripts may break unpredictably; worse, they may
WORK unpredictably. And you never know when some little helper
program may be used in such a script. Big programs are not
immune, either. Someday, someone may want to wrap up that huge
database program in a little helper script for novices, and
need that exit value.

Andrew L. Duane (JOT-7)  w:(508)-658-5600 X5993  h:(603)-434-7934
Compugraphic Corp.			 decvax!cg-atla!duane
200 Ballardvale St.		       ulowell/ \laidback
Wilmington, Mass. 01887		   cbosgd!ima/   \cgeuro
Mail Stop 200II-3-5S		     ism780c/     \wizvax

Only my cat shares my opinions, and she hasn't returned to the
invocation environment yet.

jas@ernie.Berkeley.EDU (Jim Shankland) (01/07/89)

In article <1298@tank.uchicago.edu> vevea@paideia.UUCP (Jack L. Vevea) asks
(paraphrased), why people make a fuss about lint messages that they
know to be inconsequential -- is it that a higher authority requires
that their code be lint-free, or are they just being obsessive "slaves
to lint?"

Sometimes, a higher authority does require lint-free code.  This is not
a bad thing, even if you do have to do some pretty strange things
(e.g., using "#ifdef lint") to make it happen.  Even when there is no
such higher authority, it's a good idea to arrange for code to be
completely lint-free.  While I *know* that "possible pointer alignment
problem" on return from malloc() is inconsequential, other, even
more highly paid software engineers :-) "know" that all kinds of other
lint messages are inconsequential, because the code works fine on their
VAX.  This is a sad fact; very sad, but very much a fact.

Second, if my code generates n inconsequential lint messages, then every
time I re-lint the code, I have to pick out the "real" lint, if any,
from the n inconsequential messages.  This is burdensome and error-prone.
Better to habitually use a few contrivances that eliminate the harmless
lint messages.

(Of course, the above-mentioned software engineers may then put all sorts
of unsafe weirdness into their code "to shut lint up".  Ultimately,
this is a major problem with C:  it's too easy to write non-portable code,
and too hard to specify the rules for writing portable code.  No, I'm
not proposing a solution, and I'm certainly not saying we should all
be programming in Pascal -- just pointing out a *very* costly problem
with the language.  If you doubt me, consider this small example:
what percentage of C programmers do you think know what the correct
definition of NULL is, and when NULL needs to be preceded by a type cast,
despite regular clarifications of the question in comp.lang.c?  No
fair counting those who "know" an answer that is wrong!)

Jim Shankland
jas@ernie.berkeley.edu

guy@auspex.UUCP (Guy Harris) (01/07/89)

>	I've passively watched the discussion of lint's problems with
>  exit(0) from main(), and find myself wondering why it matters.  I use
>  lint to check my code, but I've gotten into the habit of automatically
>  ignoring certain output, including 'warning:  main() returns a random
>  value to the invocation environment.'

Sometimes messages like this may *not* be inconsequential; it's probably
better to tweak your code to eliminate as many such messages as
possible, rather than to ignore them.

>  Being primarily a psychometrician, and not a professional C (or
>  any other language) programmer, I find myself wondering if some
>  of you out there are working under conditions in which some higher
>  authority requires you to produce a clean lint run as evidence
>  of good coding.

At Sun, the kernel is expected to pass "lint"; the "-h", "-b", "-x", and
"-n" flags are used, and the only messages removed (with "grep -v") are

	struct/union <XXX> never defined

and

	possible pointer alignment problem

Many times I have been *V*E*R*Y* grateful that "lint" caught coding
errors in my, and other people's, code before I tested a kernel.

>  Otherwise, it would seem to me that any concern with the message
>  would be evidence of your being a slave to lint; why else be
>  concerned when you _know_ that the warning is inconsequential?

Because, as noted, the message may *not* be inconsequential; a program
that

	1) falls off the end of "main"

and

	2) is used in a context where exit statuses are checked

may screw up.  Consider some program used in a Makefile, for instance;
if it randomly returns a non-zero exit status, and you haven't told
"make" to keep going if that command fails, your Makefile will fail. 
Yes, this really happens.

Since it's quite easy to make the complaint go away (e.g. by sticking
/*NOTREACHED*/ after the call to "exit"), it's better to do so than to
filter the complaints out.

dave@micropen (David F. Carlson) (01/07/89)

In article <1298@tank.uchicago.edu>, vevea@paideia.uchicago.edu (Jack L. Vevea) writes:
> 
> 	I've passively watched the discussion of lint's problems with
>   exit(0) from main(), and find myself wondering why it matters.  I use
...
>   Why else be concerned when you _know_ that the warning is inconsequential?

Jack, you have stumbled on the difference between an academician "playing"
with a computer and a software engineer working with one.

Just as with comments ("why do I need comments since I know what this program
does anyway?"), the purpose of linting code is not for some anal retentive
satisfaction it gives but to engineer a product such that it can be as bug-free,
sematically valid and long-term maintainable as current tools (lint, etc.)
allow.  This is what doing a good job is.  If I patch together some scaffold
test code I don't care whether it lints.  However, when I produce a for-sale
productionized piece of code I want it to be sound not only for this compiler
and this developer but for any C compiler and any future maintainers.  Lint
isn't perfect but using it is infinitely preferable to pretending that my 
programs (before linting) are without easily detectable and correctable flaws.





-- 
David F. Carlson, Micropen, Inc.
micropen!dave@ee.rochester.edu

"The faster I go, the behinder I get." --Lewis Carroll

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/07/89)

In article <1298@tank.uchicago.edu> vevea@paideia.UUCP (Jack L. Vevea) writes:
> Otherwise, it would seem to me that any concern with the message would
> be evidence of your being a slave to lint; why else be concerned when
> you _know_ that the warning is inconsequential?

Certainly if a random result really IS returned to the environment,
it's a bug, because (at least in the UNIX world) the termination
status of a process is a very important thing.

Therefore let's assume you really do know that "lint" is simply
mistaken, because of some limitation such as not realizing that
exit() never returns.  In this case, there is STILL a very good
reason for wanting to "shut lint up":  The careful portable
programmer expects absolutely NO output from "lint".  (In fact,
I achieve this nearly all the time.)  To get in the habit of
ignoring "lint" warnings is to defeat the purpose of "lint".
What if some time the "random value returned to execution
environment" warning is valid?  You'll just ignore it, but those
of us who have carefully arranged for no expected "lint" output
will certainly investigate this unexpected warning.

Ignoring certain "lint" output that could have been avoided is
one bad habit.  There is another one in the opposite direction:
Some C programmers use tricks to "shut lint up" rather than
fixing a genuinely non-portable aspect of their code.  There
aren't many cases where "lint" must be outwitted; trying to
outwit it in other cases is a mistake.

Here are things that I don't know of any way to keep "lint" from
unjustly complaining about without deliberately sabotaging it:

	return from malloc() being used other than as a (char *)

	functions like exit() that don't return

	loops that will never terminate but not patently so

	use of pointer casts

I do know how to outwit "lint" in these cases, but one needs to
be careful doing that in order not to disable a valid warning.

blarson@skat.usc.edu (Bob Larson) (01/07/89)

In article <9296@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:

>Here are things that I don't know of any way to keep "lint" from
>unjustly complaining about without deliberately sabotaging it:
>	return from malloc() being used other than as a (char *)
>	functions like exit() that don't return
>	loops that will never terminate but not patently so
>	use of pointer casts

Depending on which version of lint you use, (I've heard it is fixed
in sunos 4.0) you should add:

	varargs functions

At least one version of varargs does not allow any arguments to
the function besides va_alist, and the /*VARARGS0*/ comment does
not shut the lint I use (sunos 3.2) up.  /*VARARGSn*/ n!=0 is not
portable.  (But does have potential use in non-portable lint libraries,
etc.)

Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%ais1@ecla.usc.edu
			oberon!ais1!info-prime-request

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/07/89)

In article <14502@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
>In article <9296@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>Depending on which version of lint you use, (I've heard it is fixed
>in sunos 4.0) you should add:
>	varargs functions

Ok, that's another.

>At least one version of varargs does not allow any arguments to
>the function besides va_alist, and the /*VARARGS0*/ comment does
>not shut the lint I use (sunos 3.2) up.  /*VARARGSn*/ n!=0 is not
>portable.

Plain /*VARARGS*/ works, although it disables type checking of ALL
the arguments.  Note that the varargs specification does NOT permit
any formal parameter besides va_alist.  Even if the first argument
always has the same type, you're required to pick it up via the
va_arg macro like all the rest.

ado@elsie.UUCP (Arthur David Olson) (01/08/89)

In article <9296@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn...) writes:
> 
> Ignoring certain "lint" output that could have been avoided is
> one bad habit.  There is another one in the opposite direction:
> Some C programmers use tricks to "shut lint up" rather than
> fixing a genuinely non-portable aspect of their code.

Indeed.  One local addition to "lint" is illustrated below:

	Script started on Sat Jan  7 12:51:10 1989
	elmer$ cat try.c
	/*LINTLIBRARY*/

	/*ARGSUSED*/
	int
	func(i)
	{
		return i;
	}
	elmer$ lint try.c
	try.c:
	try.c(8): warning: function func has superfluous ARGSUSED
	elmer$ exit

	script done on Sat Jan  7 12:51:27 1989

It surprises me how much off-the-net code produces "superfluous ARGSUSED"
messages; some C programmers just uniformly use tricks, whether they're
needed or not.
-- 
Wolf is a registered trademark of the boy who cried it.
-- 
	Arthur David Olson    ado@ncifcrf.gov    ADO is a trademark of Ampex.

jbn@glacier.STANFORD.EDU (John B. Nagle) (01/08/89)

In article <806@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>>	I've passively watched the discussion of lint's problems with
>>  exit(0) from main(), and find myself wondering why it matters.  
      
      Any UNIX program that returns a random exit status is broken.

					John Nagle

bill@twwells.uucp (T. William Wells) (01/08/89)

In article <1298@tank.uchicago.edu> vevea@paideia.UUCP (Jack L. Vevea) writes:
:       I've passively watched the discussion of lint's problems with
:   exit(0) from main(), and find myself wondering why it matters.  I use
:   lint to check my code, but I've gotten into the habit of automatically
:   ignoring certain output, including 'warning:  main() returns a random
:   value to the invocation environment.'  Being primarily a psychometrician,
:   and not a professional C (or any other language) programmer, I find myself
:   wondering if some of you out there are working under conditions in which
:   some higher authority requires you to produce a clean lint run as
:   evidence of good coding.  Otherwise, it would seem to me that any
:   concern with the message would be evidence of your being a slave to
:   lint; why else be concerned when you _know_ that the warning is
:   inconsequential?

Here are the two reasons why one deals with this:

    1) Having put an exit() in the program, you should add
       /*NOTREACHED*/ right after it; this tells lint that you know
       what you are doing.

    2) If you do 1), as you should, getting the lint message means you
       screwed up: you didn't put an exit() or return where it
       belongs.

In short, if you are in the habit of ignoring this particular message,
you should change your habit. Always do 1) and, should you get the
message, investigate and fix the problem.

---
Bill
{ uunet!proxftl | novavax } !twwells!bill

guy@auspex.UUCP (Guy Harris) (01/10/89)

Why I Hate Attribution Lines, #5,638:

>In article <806@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>>>	I've passively watched the discussion of lint's problems with
>>>  exit(0) from main(), and find myself wondering why it matters.

I didn't write that, the person to whom I was responding wrote that.

danw@tekchips.CRL.TEK.COM (Daniel E. Wilson) (01/18/89)

In article <17985@glacier.STANFORD.EDU>, jbn@glacier.STANFORD.EDU (John B. Nagle) writes:
> In article <806@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
> >>	I've passively watched the discussion of lint's problems with
> >>  exit(0) from main(), and find myself wondering why it matters.  
>       
>       Any UNIX program that returns a random exit status is broken.
> 
  I agree.  Please find something else about lint to complain about.

Dan Wilson

guy@auspex.UUCP (Guy Harris) (01/19/89)

>> In article <806@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>> >>	I've passively watched the discussion of lint's problems with
>> >>  exit(0) from main(), and find myself wondering why it matters.  

No, I didn't say anything like that.  *I* know why it matters.  PLEASE
either check your attributions VERY carefully, or simply delete them, so
as to avoid confusion.