|
On 20/11/2006, at 3:16 PM, Vernon Hamberg wrote:
Why? Because it is the generally accepted recommendation - as stated by Jon Paris as follows in his "Who Knew You Could..." redbook:
1) But it's not a generally recommended practice in C programming and errno is a C run-time attribute 2) Jon wasn't the only author of that Red Book so it's possible this recommendation came from a different source. 3) Even if Jon wrote the quote below I think he is wrong for recommending it. My view is the same as Scott's on this one.
If you want to quote someone who knows what he's talking about** then you'd be hard-pressed to find a more authoritative source than W. Richard Stevens. From "Advanced Programming in the Unix Environment"" "There are two rules to be aware of with respect to errno. First, its value is never cleared by a routine if an error does not occur. Therefore, we should examine its value only when the return value from a function indicates that an error occurred. Second, the value of errno is never set to 0 by any of the functions, and none of the constants defined in <errno.h> have a value of 0."
To me that says that testing errno for a non-zero value is valid but testing it for 0 is not valid.
** Not suggesting that Jon doesn't know what he's talking about but in this particular case, if he is the originator of the quote to which you refer, then he's wrong.
The error code is made available by the GetErrNo() function, which is aremapped __error() C function. The GetErrNo() function gets access to the ErrNo variable through a pointer. The ErrNo variable contains the error code. Before issuing any function that returns an error code, the ErrNo variable should becleared. However, it is possible only after the GetErrNo() function was performed. If the error code is not cleared before the function is entered, the resulting error code may be false.
Only if you write code that checks errno without first checking the function return value to see if errno SHOULD be checked. If you do that then you are wrong.
errno - as I know you know - is a global variable used by everything - it is not changed if not error occurs, so setting it to 0 just before a function that might set it and then checking it after is how I understand doing this.
You can't rely on the function you call AFTER setting errno to zero to be the only thing that may change it. You and others are suggesting (or defending):
set erro no to zero call OS function X() check errno is still zeroHowever you have no way of knowing what other functions are called by X(). It may call Y() which might fail and set errno. X() might handle this condition and therefore return successfully leaving errno to whatever Y() set it. Checking errno to determine success or failure in this case is obviously flawed.
A similar situation can happen in application code that wraps multiple OS functions into one higher-level function--especially if it handles the error condition. Unless you have the practice of always resetting errno to zero after testing it you run the risk of getting a false error condition. Note that IF you did this sort of thing you would be flouting existing convention regarding errno.
Because you CANNOT know what happens to errno after you call an OS function the only thing you can do is check the function return value for an error indication PRIOR to testing errno.
Not all functions return an error code - an example is StrToD - it returns a float value - it is commonly used to test whether a string is numeric - the only reliable test for errors is to set errno - theglobal variable - before calling StrToD and then checking it after the call.
strtod() is not a very reliable way of determining if a string is numeric. Like most of these C conversion functions it makes a best effort and never actually fails. It simply stops checking when it finds a character that is not a valid digit. strtod() does have two pseudo error conditions:
a) overflow b) underflowOverflow returns HUGE_VAL. Underflow returns zero. In these cases errno might be set to ERANGE but not always. So checking result for +HUGE_VAL or -HUGE_VAL or zero might indicate an error. HUGE_VAL is probably an error but zero is a valid floating point value so might not indicate an error. I've had strtod() return zero in an underflow condition but errno has remained at zero. No way to tell whether zero is the correct result. Given that errno is not always set by this function it's not reliable to rely on it.
If you do use strtod() to check for a numeric string it is the endptr string that must be checked, not the return value. Because the return value is the only thing that MIGHT be affected by errno it follows that errno can't be reliably used on its own either and certainly not to determine whether a string is numeric.
Tightly coupling the setting and checking will not cause problems with other functions, as far as I know.
See suggested example above. Regards, Simon Coulter. -------------------------------------------------------------------- FlyByNight Software AS/400 Technical Specialists http://www.flybynight.com.au/ Phone: +61 3 9419 0175 Mobile: +61 0411 091 400 /"\ Fax: +61 3 9419 0175 \ / X ASCII Ribbon campaign against HTML E-Mail / \ --------------------------------------------------------------------
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.