From: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: Fri Aug 1, 2003 6:32:52 PM Europe/London
To: "Chris B. Vetter" <chrisv@web4inc.com>
Subject: Re: NSLog() / NSLogv() annoyance
On Friday, August 1, 2003, at 05:55 PM, Chris B. Vetter wrote:
On Fri, 1 Aug 2003 15:46:05 +0100
Richard Frith-Macdonald <richard@brainstorm.co.uk> wrote:
[...]
I know you know this but ... it's easy to overlook when you are used
to working with objects ... in C/ObjC, function arguments are passed
by value rather than by reference.
This means that if (the value of) errno is passed as an argument to
NSLog, the value logged will be the original value passed
irrespective
of any changes to the contents of the errno
variable which might be made inside NSLog itsself.
Any other behavior is a compiler bug.
Yes, but check an earlier mail I sent. If you do a system call, then
use
NSLog() to print some info regarding the call, and then check errno,
errno is set to 2, which is a bad thing (IMHO) since the error
referred
to by errno is a result of calling NSLog() not the system call as
you'd
expect. Example:
// error is zero on success, non-zero on failure and errno
// will be set to the actual error number...
error = getaddrinfo(hostname, NULL, &hints, &address);
if( 0 != error )
NSLog(@"getaddrinfo() for host %s returns: %s",
hostname, gai_strerror(errno));
// Now here we'll run into a problem...
switch( errno )
{
case EAI_ADDRFAMILY:
NSLog(@"address domain not supported");
return nil;
case EAI_AGAIN:
// temporary error, try again...
[...]
default:
// can't recover
return nil;
}
The problem here is, that by calling NSLog(), errno will be set to 2.
HOWEVER, EAI_AGAIN is (at least on BSD) also defined as 2.
You can imagine what will happen...
True but, with respect, that's bad programming ...
It is normal/conventional to allow for the possibility of errno being
modified
by function calls. For instance, if you used fprintf() rather than
NSLog() you
would have the same problem (ie fprintf() could change errno), so your
code
needs to be structured to save errno in a local variable before doing
anything
that might change it.
While having NSLog() defy convention and save/restore errno
(and documenting that fact) could be useful, I think it introduces an
incompatibility
with MacOS-X nd OPENSTEP, where the value of errno after a call to
NSLog()
is (I assume) undefined.
If code is written to depend on this feature, it would be less
portable (not a
problem for me, but it might be for others).