andrew@teletron.UUCP (Andrew Scott) (09/15/87)
I've noticed something odd while working with pointers to functions. Specifically, I have a chunk of code which is simulating a function call. The code pushes a return address onto the "stack" (declared as an integer array) like so: void foo() { /* do some stuff */ } void push() { extern int *stack_ptr; *(--stack_ptr) = (int) foo; } Lint returns the following messages: (10) operands of CAST have incompatible types (10) operands of = have incompatible types However, lint is happy if I declare `foo' as: int foo() { /* do some stuff */ } In either case, the compiler says nothing and produces the intended code result. Is my version of lint broken? I would have thought that a cast from a function pointer to an integer would be the same thing for any function, no matter what type value it returns (including void). Andrew
pts@watt.acc.Virginia.EDU (Paul T. Shannon) (01/10/89)
I've been following the lint discussion, and decided it was high time for me to use lint myself. Here's a question for style experts: Lint complains: function returns value which is always ignored fprintf printf Is it bad style to use these functions without also checking the returned value?
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/10/89)
In article <491@babbage.acc.virginia.edu> pts@watt.acc.Virginia.EDU (Paul T. Shannon) writes: >function returns value which is always ignored > fprintf printf >Is it bad style to use these functions without also checking the >returned value? Since these functions can, and at times do, fail, in a robust program you should indeed test their return values and take proper error- recovery actions. The one possible exception is (void)fprintf(stderr, "...: operation failed\n"); because if a write to the standard error output fails, you may have just exhausted your error-recovery resources and can do no better anyway. (What are you going to do, complain about THAT failure on stderr?) Note the use of a (void) cast to explicitly discard an unused function value. This should not be done lightly; if properly used, it indicates that the programmer realized that the function returns a value but that it is not necessary in this particular instance to use the value. This will shut lint up, but that should not be the prime motivation for using the cast!
peter@ficc.uu.net (Peter da Silva) (01/10/89)
In article <9322@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: > The one possible exception is > (void)fprintf(stderr, "...: operation failed\n"); > because if a write to the standard error output fails, you may have just > exhausted your error-recovery resources and can do no better anyway. > (What are you going to do, complain about THAT failure on stderr?) if(fprintf(stderr, "...: operation failed\n") == FAIL) { if(!(fp = fopen("/dev/tty", "w"))) { if(!(fp = fopen("/dev/console", "w"))) { chdir("/tmp"); abort(); } } (void)fprintf(fp, "...: operation failed\n"); fclose(fp); } And to be totally safe, use open()... Not entirely smiley. There are programs that don't have 0, 1, and 2 open for lengths of time. Like, a modem callback program... -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180. `-_-' Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net. 'U` Opinions may not represent the policies of FICC or the Xenix Support group.
bill@twwells.uucp (T. William Wells) (01/10/89)
In article <491@babbage.acc.virginia.edu> pts@watt.acc.Virginia.EDU (Paul T. Shannon) writes:
: I've been following the lint discussion, and decided it was high
: time for me to use lint myself. Here's a question for style experts:
: Lint complains:
:
: function returns value which is always ignored
: fprintf printf
:
: Is it bad style to use these functions without also checking the
: returned value?
The return values of the printf family functions are not very
consistently defined. Because of this, one should never use their
return value. You have to do the checking of printf before the
printf executes, i.e., either at the time you write the code or in
the code itself before the printf executes. (Except that I/O errors
need to be checked sometime after a flush has need done. But that is
another can of worms entirely, caused by standard I/O buffering.)
I just ignore the lint message. On the other hand, if it said that
the function values were *sometimes* ignored, I'd go hunting for the
portability problem caused by using the return value.
---
Bill
{ uunet!proxftl | novavax } !twwells!bill
dwp@k.gp.cs.cmu.edu (Doug Philips) (01/11/89)
gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
:Note the use of a (void) cast to explicitly discard an unused
:function value. This should not be done lightly; if properly used,
:it indicates that the programmer realized that the function returns
:a value but that it is not necessary in this particular instance to
:use the value. This will shut lint up, but that should not be the
:prime motivation for using the cast!
Actually, my prime motivation for using it IS to shut up lint.
Strcpy and strcat return values that I almost never care about. Lint
doesn't understand the "return value for the convenience of sometimes
having it" notion. Perhaps this is a candidate for another SLM like
'vstrcat'?? ;-)
--
Doug Philips "All that is gold does not glitter,
Carnegie-Mellon University Not all those who wander are lost..."
dwp@cs.cmu.edu -J.R.R. Tolkien
--
djones@megatest.UUCP (Dave Jones) (01/11/89)
In article <9322@smoke.BRL.MIL), gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
) The one possible exception is
) (void)fprintf(stderr, "...: operation failed\n");
) because if a write to the standard error output fails, you may have just
) exhausted your error-recovery resources and can do no better anyway.
) (What are you going to do, complain about THAT failure on stderr?)
)
Nope. But under Unix, I'll complain on file-descriptor 2, if I think
that might help.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/11/89)
In article <2679@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: > if(fprintf(stderr, "...: operation failed\n") == FAIL) { > if(!(fp = fopen("/dev/tty", "w"))) { > if(!(fp = fopen("/dev/console", "w"))) { Not really, because if somebody has redirected stderr it is probably for a good reason, and such policy should not be overridden by an application that doesn't know what's going on outside. Blathering on the console is particularly obnoxious in most cases.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/11/89)
In article <1172@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes: >Nope. But under Unix, I'll complain on file-descriptor 2, if I think >that might help. On UNIX, if stderr is not associated with FD 2, you would probably be making a mistake to scribble on FD 2.
ftw@masscomp.UUCP (Farrell Woods) (01/11/89)
In article <491@babbage.acc.virginia.edu> pts@watt.acc.Virginia.EDU (Paul T. Shannon) writes: >I've been following the lint discussion, and decided it was high >time for me to use lint myself. Here's a question for style experts: >Lint complains: > >function returns value which is always ignored > fprintf printf > >Is it bad style to use these functions without also checking the >returned value? Since the printf() family of functions is writing something to somewhere, they return the number of bytes written (and -1 if they failed). If you want to ignore the return value and be in style (;-)), you can use a void cast: (void)printf(....); This signals that you are explicitly ignoring the returned value. -- Farrell T. Woods Voice: (508) 692-6200 x2471 MASSCOMP Operating Systems Group Internet: ftw@masscomp.com 1 Technology Way uucp: {backbones}!masscomp!ftw Westford, MA 01886 OS/2: Half an operating system
guy@auspex.UUCP (Guy Harris) (01/12/89)
>The return values of the printf family functions are not very >consistently defined. Because of this, one should never use their >return value. More correctly: There exist at least two definitions of the return values of the printf family functions. Because of this, you should only use their return value if you know your software will be built only in environments where one particular definition is in effect. The System V definition has them returning the number of characters printed on success, or EOF on failure, and this is also the definition in the current dpANS. Thus, this definition will become more common in the future; eventually, most, if not all, systems will use this definition. Even UNIX systems that "started with 4BSD" often have environments in which this definition is used.
peter@ficc.uu.net (Peter da Silva) (01/12/89)
In article <9332@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: > In article <2679@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: > > if(fprintf(stderr, "...: operation failed\n") == FAIL) { > > if(!(fp = fopen("/dev/tty", "w"))) { > > if(!(fp = fopen("/dev/console", "w"))) { > Not really, because if somebody has redirected stderr it is probably > for a good reason, and such policy should not be overridden by an > application that doesn't know what's going on outside. Blathering > on the console is particularly obnoxious in most cases. You're right. I should probably have included a reference to "/dev/smiley" in there. Blathering to "/dev/tty" is a different matter. If you can't open /dev/tty, then something is pretty wrong. What happens if you do this: fclose(stdin); fclose(stdout); fclose(stderr); setpgrp(); if(!(fp = fopen("/dev/tty", "w+"))) { ... } But for an application (like a modem callback program) that DOES know what's going on outside might be perfectly justified in blathering on the console. -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180. `-_-' Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net. 'U` Opinions may not represent the policies of FICC or the Xenix Support group.
maujt@warwick.ac.uk (Richard J Cox) (01/13/89)
In article <317@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes: >In article <491@babbage.acc.virginia.edu> pts@watt.acc.Virginia.EDU (Paul T. Shannon) writes: >: function returns value which is always ignored >: fprintf printf >: >: Is it bad style to use these functions without also checking the >: returned value? > >The return values of the printf family functions are not very >consistently defined. Because of this, one should never use their >return value. You have to do the checking of printf before the There are situations where you have to check the return values. e.g. when fprinting to a pipe or socket, in this case the process at the other end of the pipe may have died, and in this case the fprintf _will_fail_. This was causing a major bug in a program I wrote, and it was in pure desperation I checked the return value. - RC /*--------------------------------------------------------------------------*/ JANET: maujt@uk.ac.warwick.cu BITNET: maujt%uk.ac.warwick.cu@UKACRL ARPA: maujt@cu.warwick.ac.uk UUCP: maujt%cu.warwick.ac.uk@ukc.uucp Richard Cox, 84 St. Georges Rd, Coventry, CV1 2DL; UK PHONE: (0203) 520995
maujt@warwick.ac.uk (Richard J Cox) (01/13/89)
In article <2679@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: >In article <9322@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: > >Not entirely smiley. There are programs that don't have 0, 1, and 2 open >for lengths of time. Like, a modem callback program... Or any daemon, especially where you have a daemon fprintf'ing to sockets, connected to processes that may have died..... - RC /*--------------------------------------------------------------------------*/ JANET: maujt@uk.ac.warwick.cu BITNET: maujt%uk.ac.warwick.cu@UKACRL ARPA: maujt@cu.warwick.ac.uk UUCP: maujt%cu.warwick.ac.uk@ukc.uucp Richard Cox, 84 St. Georges Rd, Coventry, CV1 2DL; UK PHONE: (0203) 520995
henry@utzoo.uucp (Henry Spencer) (01/16/89)
In article <491@babbage.acc.virginia.edu> pts@watt.acc.Virginia.EDU (Paul T. Shannon) writes: >function returns value which is always ignored > fprintf printf > >Is it bad style to use these functions without also checking the >returned value? A troublesome point. Although in general one should always check the return values from functions that might fail, printf is a singularly annoying case of a function that could fail but very rarely does, and is a pain to check -- especially since the type of its returned value is not portable among current Unixes. My own inclination is to list it in the "utter paranoia" category, to be checked if something crucial is at stake (e.g. loss of user data), and to assume that otherwise the failure is likely to be noticed without explicit attention. Stdio is a glaring example of a library package that would benefit greatly from a better error-handling mechanism. -- "God willing, we will return." | Henry Spencer at U of Toronto Zoology -Eugene Cernan, the Moon, 1972 | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
bet@dukeac.UUCP (Bennett Todd) (01/17/89)
>Lint complains: > >function returns value which is always ignored > fprintf printf > >Is it bad style to use these functions without also checking the >returned value? *All* possible error routines should be checked, with only one exception that I know of: if (fatal failure) { (void) fprintf(stderr, "suitable error message"); exit(error_level); } There's no point in checking for an error writing to stderr, since you couldn't report it anyway, and all you are going to do is exit. I found that wrapping suitable error checking and disposal around every last function call got tedious, fast. So, I started a library of routines (up to 20 now; I add more as needed) which are simply wrappers around system calls (section 2 UPM) and library routines (section 3 UPM) which check the status of the called routine, and if it failed, print a suitable message and exit. So, in the usual case (seems to be better than 90% of the time) I just use the efunc_name() routine and am done with it. For example, ewrite() and efwrite() are of type void, whereas efopen() is of type FILE * and guaranteed to return a valid FILE pointer (or not come back at all). As long as I was inserting my own layer between my code and stdio, I added as a frill cacheing filenames in eopen() and efopen(), for use in diagnostic messages. Also, emalloc() prepends and appends validation signatures to each allocated unit, which erealloc() and efree() check. So, diagnostics are delivered as soon as possible after you corrupt the malloc arena. This sort of approach makes life much easier for me in writing and debugging programs. -Bennett bet@orion.mc.duke.edu
geoff@warwick.UUCP (Geoff Rimmer) (01/17/89)
In article <1989Jan16.080743.2424@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: > [...] >printf ... >is a pain to check -- especially since the type of its returned value >is not portable among current Unixes. I thought that problem was only with sprintf, where on some systems it returns the string it has just produced, and on others the number of characters written to the string. I understood that both printf and fprintf return int (# chars printed) on every system. cat > /usr/include/std/flame-inviter.h Please correct me if I'm wrong. ^D #include <std/flame-inviter> Geoff ------------------------------------------------------------ Geoff Rimmer, Computer Science, Warwick University, England. geoff@uk.ac.warwick.emerald "Well I think it's rubbish. I'm going to vomit." "I can think of no higher compliment." - Filthy Rich and Catflap, 1986. ------------------------------------------------------------
chip@ateng.ateng.com (Chip Salzenberg) (01/18/89)
According to henry@utzoo.uucp (Henry Spencer): >[...] printf is a singularly >annoying case of a function that could fail but very rarely does, and >is a pain to check -- especially since the type of its returned value >is not portable among current Unixes. One portable solution would be an occasional test of ferror(stdout). -- Chip Salzenberg <chip@ateng.com> or <uunet!ateng!chip> A T Engineering Me? Speak for my company? Surely you jest! "It's no good. They're tapping the lines."
jcbst3@cisunx.UUCP (James C. Benz) (01/18/89)
In article <9322@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >you should indeed test their return values and take proper error- >recovery actions. The one possible exception is > (void)fprintf(stderr, "...: operation failed\n"); >because if a write to the standard error output fails, you may have just Okay, so where does one find out what error codes are returned from these stdio functions? The UNIX (AT&T 3B2) manuals I have say nothing in printf(3S) about error codes, and stdio(3S) says "Individual function descriptions describe the possible error conditions" Sounds like Catch 22 to me.
guy@auspex.UUCP (Guy Harris) (01/18/89)
>Okay, so where does one find out what error codes are returned from these >stdio functions? The UNIX (AT&T 3B2) manuals I have say nothing in printf(3S) >about error codes, If by "error codes" you mean something like "errno" codes, "printf"-family routines don't return them, but then *no* UNIX routine I know of returns one - they all "return" them by setting "errno". The section 2 manual pages explicitly list values to which "errno" will be set (although the lists are quite often incomplete); unfortunately, most section 3 manual pages don't. By and large, you can probably expect that they can return any of the ones "read" or "write" can return ("write" in the case of "printf", for example), and that they *may* return any of the others. If you mean "how can I test to see if they got an error *at all*," the AT&T 3B2 S5R3 manual says: Each function returns the number of characters transmitted (not counting the \0 in the case of "sprintf"), or a negative value if an output error is encountered. in the first paragraph; perhaps earlier documentation didn't say this. The dpANS (or is it a pANS now?) says basically the same thing. Some older versions of UNIX, and some other versions of UNIX, or environments within those vesrions, that maintain compatibility with those older versions, have different return values (0 on success, -1 on error), but over time those versions will most likely adopt the dpANS conventions.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/19/89)
In article <15024@cisunx.UUCP> jcbst3@unix.cis.pittsburgh.edu (James C. Benz) writes: >Okay, so where does one find out what error codes are returned from these >stdio functions? The UNIX (AT&T 3B2) manuals I have say nothing in printf(3S) >about error codes, and stdio(3S) says "Individual function descriptions >describe the possible error conditions" Sounds like Catch 22 to me. I don't know what you mean by "error codes". The printf(3S) description in the SVR3.0 PRM clearly states that the *printf() functions return the number of characters transmitted, or a negative number in case of error. (Happens that the negative number is -1, but you're not supposed to know that.) As with all UNIX system service-related operations, if some system call failed, the extern int "errno" is set to hold one of the error numbers described in the introduction to section 2 of the manual. However, library functions such as printf(3S) can fail for reasons other than system call failure, and even a successful printf(3S) may have generated a system call failure on the way (typically a failed ioctl(2) invocation to determine whether the stream is associated with a terminal), so it is unwise to rely on the contents of errno to tell you anything meaningful about the causes of printf(3S) errors. Just consider them "mysterious failures" and take appropriate recovery steps.
bph@buengc.BU.EDU (Blair P. Houghton) (01/20/89)
In article <1188@dukeac.UUCP> bet@dukeac.UUCP (Bennett Todd) writes: >*All* possible error routines should be checked, with only one exception that >I know of: > > if (fatal failure) { > (void) fprintf(stderr, "suitable error message"); > exit(error_level); > } > >There's no point in checking for an error writing to stderr, since you >couldn't report it anyway, and all you are going to do is exit. Howsabout if the poor return from fprintf indicates that stderr is missing, and you therefore specify logging the unreportable errors to a file? --Blair
gvr@cs.brown.edu (George V. Reilly) (03/14/90)
Given the following code, lint complains: point.c(33): warning: evaluation order for ``dx'' undefined The complaint turns out to be caused by the subexpression (dx *= dx) Surely, the parenthesization and comma operators make the whole expression well defined? ========================================================================= typedef struct { int x, y; } Point; /* ---------------------------------------------------------------------- * * closest_point(): Return the index of point |pt| within * point-table |table| of size |n|. Return -1 on error. * * ---------------------------------------------------------------------- */ int closest_point(pt, table, n) Point pt; Point table[]; int n; { register int min = MAXINT, dist, dx, dy, result = -1, x, y; x = pt.x; y = pt.y; while (--n >= 0) { /* Ugly but efficient test for proximity */ if (((dx = table[n].x - x), ((dx *= dx) < min)) && ((dy = table[n].y - y), ((dist = dx + dy*dy) < min))) { result = n; min = dist; } } return (result); } ========================================================================= ________________ George V. Reilly gvr@cs.brown.edu uunet!brunix!gvr gvr@browncs.bitnet Box 1910, Brown U, Prov, RI 02912
CMH117@psuvm.psu.edu (Charles Hannum) (03/14/90)
In article <32699@brunix.UUCP>, gvr@cs.brown.edu (George V. Reilly) says: > > if (((dx = table[n].x - x), ((dx *= dx) < min)) && ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ The C compiler could calculate these expressions in any way it damned well feels like it. This is not defined in the ANSI C standard, mainly because it would screw up optimizing compilers to have limits on the order of evaluation when not necessary. Virtually, - Charles Martin Hannum II "Klein bottle for sale ... inquire within." (That's Charles to you!) "To life immortal!" cmh117@psuvm.{bitnet,psu.edu} "No noozzzz izzz netzzzsnoozzzzz..." c9h@psuecl.{bitnet,psu.edu} "Mem'ry, all alone in the moonlight ..."
utility@quiche.cs.mcgill.ca (Ronald BODKIN) (03/15/90)
In article <90072.232413CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes: >> if (((dx = table[n].x - x), ((dx *= dx) < min)) && >The C compiler could calculate these expressions in any way it damned well >feels like it. This is not defined in the ANSI C standard... So, in general, the expression a, b does not define an order of operations? I had assumed that writing a, b allowed sequential operations to be performed in computing expressions (great for macros). Ron
CMH117@psuvm.psu.edu (Charles Hannum) (03/15/90)
In article <90072.232413CMH117@psuvm.psu.edu>, Charles Hannum <CMH117@psuvm.psu.edu> says: > >In article <32699@brunix.UUCP>, gvr@cs.brown.edu (George V. Reilly) says: >> >> if (((dx = table[n].x - x), ((dx *= dx) < min)) && > ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ >The C compiler could calculate these expressions in any way it damned well >feels like it. This is not defined in the ANSI C standard, mainly because >it would screw up optimizing compilers to have limits on the order of >evaluation when not necessary. Okay. It looks like I was wrong about this. NOW QUIT SENDING ME HATE MAIL!!! Virtually, - Charles Martin Hannum II "Klein bottle for sale ... inquire within." (That's Charles to you!) "To life immortal!" cmh117@psuvm.{bitnet,psu.edu} "No noozzzz izzz netzzzsnoozzzzz..." c9h@psuecl.{bitnet,psu.edu} "Mem'ry, all alone in the moonlight ..."
sanders@sanders.austin.ibm.com (Tony Sanders) (03/16/90)
In article <90072.232413CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes: > >In article <32699@brunix.UUCP>, gvr@cs.brown.edu (George V. Reilly) says: >> >> if (((dx = table[n].x - x), ((dx *= dx) < min)) && > ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ >The C compiler could calculate these expressions in any way it damned well >feels like it. This is not defined in the ANSI C standard, mainly because >it would screw up optimizing compilers to have limits on the order of >evaluation when not necessary. Not so fast! The only place where comma order is undefined is in function calls. The comma OPERATOR has left to right evaluation order. Anyway, this problem isn't related at all to the comma operator anyway, read on. The problem lies not in the (self admited) ugly if statement but in the use of "dx *= dx" itself. For example a simple "r = (x*=x);" will also complain of evaluation order undefined (with my lint). While "r = (x=x*x);" slips by lint without a word (as it should). Sounds like a lint bug to me. As ugly as the if statement was, it is prefectly legal code. If you want the code to lint clean just change the "dx*=dx" to "dx=dx*dx". However, I higly suggest rethinking the problem and make the code "cleaner". -- sanders The 11th commandment: "Thou shalt use lint" For every message of the day, a new improved message will arise to overcome it. Reply-To: cs.utexas.edu!ibmaus!auschs!sanders.austin.ibm.com!sanders (ugh!)