LWN.net Logo

_must_check

_must_check

Posted Nov 23, 2006 8:26 UTC (Thu) by ldo (subscriber, #40946)
Parent article: KHB: Automating bug hunting

I personally don't understand the point of _must_check. I would prefer to see a GCC option that caused all calls to functions that return non-void results to produce compile-time errors unless the result is

  • used in an expression (including an assignment), or
  • explicitly cast to void.

Thus, for example, a call to unlink(2) like this:

unlink(filename);

would be illegal. If you really wanted to ignore the result, you would have to write:

(void)unlink(filename);

which would make it clear to any reader that a function result was being thrown away.


(Log in to post comments)

_must_check

Posted Nov 23, 2006 11:09 UTC (Thu) by gnb (subscriber, #5132) [Link]

That would be fine if APIs were designed with that in mind, but as things
stand you probably need to be more selective because of commonly used
functions that return values no-one cares about. The most obvious
user-space example is printf. A quick look at google codesearch suggests
that about 0% of the world's programming population checks the return
value (understandably). So a global option probably wouldn't get used
much due to the amount of code that would need "fixing". Having a
case-by-case "no, really _must_ check this one" is messier but likely
to meet less resistance.

_must_check

Posted Nov 23, 2006 15:12 UTC (Thu) by nix (subscriber, #2304) [Link]

Also, (void)blah is *really ugly*. To me casts to void look *wrong*. They only really make sense in the context of C++ templates (for the same reason that returning `values of type void' can sometimes make sense there).

Re: _must_check

Posted Nov 24, 2006 1:30 UTC (Fri) by ldo (subscriber, #40946) [Link]

>Also, (void)blah is *really ugly*. To me casts to void look *wrong*.

It's either

(void)unlink(filename);

or

ignore_unwanted_result = unlink(filename);

Which would you prefer?

Re: _must_check

Posted Nov 24, 2006 21:58 UTC (Fri) by nix (subscriber, #2304) [Link]

Since the whole point of __attribute__((warn_unused_result)) is that it
should be applied only to functions where it is nearly always a mistake to
ignore the result at all, the question is academic.

The problem with (in effect) adding that attribute to every function is
that it *would* require one ugly workaround or another, and thus would
encourage using such workarounds even for those functions where it *is* an
error to ignore the result. This would eliminate a large part of the point
of warn_unused_result, and reduce net security.

(I've seen exactly this happen on codebases that frequently get attacked
by IMHO flawed lint tools that *do* emit such warnings as you propose.
(void)foo() crops up whenever foo()'s result is ignored, *even when
ignoring that result is in fact a bad idea*.)

Re: _must_check

Posted Nov 30, 2006 2:05 UTC (Thu) by ldo (subscriber, #40946) [Link]

>Since the whole point of __attribute__((warn_unused_result)) is that
>it should be applied only to functions where it is nearly always a
>mistake to ignore the result at all, the question is academic.

On the contrary, the question is far from academic. This business of having to ignore return values by assigning them to rubbish variables (as opposed to simply casting them to void) has already infected the Linux kernel--and indeed, led to bugs there. A clean, uniform solution is needed.

Re: _must_check

Posted Nov 28, 2006 4:30 UTC (Tue) by xoddam (subscriber, #2322) [Link]

How about
#define do (void)
?

Re: _must_check

Posted Nov 28, 2006 23:56 UTC (Tue) by nix (subscriber, #2304) [Link]

That particular choice of name kinda wrecks do/while loops, don't you
think?

Re: _must_check

Posted Nov 29, 2006 2:03 UTC (Wed) by xoddam (subscriber, #2322) [Link]

Oh yes. I'll get my coat.

_must_check

Posted Dec 2, 2006 22:02 UTC (Sat) by jzbiciak (✭ supporter ✭, #5246) [Link]

(void)strcpy(buf, "That's just plain silly.\n");

for (i = 0; i < 100; (void)i++)
    (void)printf("%s", buf);

(void)fflush(stdout);


I think if you required (void) casts on all ignored return values, you'd quickly find yourself adding them blindly, and/or probably going (void)just this (void)side of (void)insane. (void)(void)(VOID)

_must_check

Posted Dec 2, 2006 22:03 UTC (Sat) by jzbiciak (✭ supporter ✭, #5246) [Link]

Oh, and imagine requiring that for C++. Recall that operator= returns the assigned value.... (void)a = b; Ok, maybe that's a bit over-the-top, but really, where do you draw the line?

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds