On Tue, Jan 26, 2010 at 11:23:18AM -0800, Blair Zajac wrote: > On 01/26/2010 10:32 AM, Stefan Sperling wrote: > >I've been told some time ago, by long-time unix hackers, > >that clearning errno is usually not necessary, one of the few > >exceptions to this rule being the strtol() family of functions. > >I didn't account for this exception when writing the log message, > >which was wrong. > > My understand is that if you ever need to check the errno then you > should set it 0 yourself because system and library calls will not > set it to 0 for you.
Usually you won't compare errno to zero, but to some known value which the function in question will set errno to in case of failure. The failure itself is not indicated via errno, but through other means, like the return value. Examining errno then gives you the reason for the failure. E.g. if open(2) fails, it indicates failure by returning -1. You would then check errno for a number of values, e.g. ENOTDIR, ENAMETOOLONG, ENOENT, EACCES, etc. to find out what happened. But in case open returns a valid fd, you can just go on and use the fd. errno won't contain interesting information. > How is strtol() different? If the parsed number is out of range, strtol() uses errno as the only channel to signal an error. Actually, the same applies to apr_strtoi64(), so I really should not have made the change which prompted this discussion! A better interface would probably require allocating the converted number and returning a pointer to it. Then it could return NULL on failure, instead of something which looks like a number. For reference: http://www.openbsd.org/cgi-bin/man.cgi?query=strtol Ensuring that a string is a valid number (i.e., in range and containing no trailing characters) requires clearing errno beforehand explicitly since errno is not changed on a successful call to strtol(), and the re- turn value of strtol() cannot be used unambiguously to signal an error: char *ep; long lval; ... errno = 0; lval = strtol(buf, &ep, 10); if (buf[0] == '\0' || *ep != '\0') goto not_a_number; if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) goto out_of_range; Stefan

