[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: NSLog() / NSLogv() annoyance
From: |
Alexander Malmberg |
Subject: |
Re: NSLog() / NSLogv() annoyance |
Date: |
Sun, 03 Aug 2003 03:53:48 +0200 |
Richard Frith-Macdonald wrote:
[snip]
> > The only thing is that you might want to do something like call some
> > library function and if there was an error, print it out, like:
> >
> > file = fopen("/dev", "w");
> > if (file == NULL)
> > NSLog(@"Got an error opening /dev, errno = %d", errno);
> >
> > GNUstep will (more than likely) print out the wrong error number,
> > since there are hidden library calls in NSLog, MacOSX will print out
> > the correct value. I'm not sure if you should rely on this being
> > correct though.
>
> 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.
The exception would be if NSLog() was a #define function, and not a
normal c function. NSLog isn't, but eg. NSDebugLog is:
#define NSDebugLog(format, args...) \
do { if (GSDebugSet(@"dflt") == YES) \
NSLog(format , ## args); } while (0)
If GSDebugSet() makes calls that affect errno, the value passed to NSLog
will be incorrect. GSDebugSet() seems ok, but there are others
(GSDebugFunctionMsg) that are highly suspicious. For example, this will
print the wrong errno:
#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
#include <Foundation/NSDebug.h>
#include <errno.h>
int main(int argc,char **argv)
{
errno=atoi(argv[1]);
NSDebugFLog(@"errno=%i %m\n",errno);
return 0;
}
(don't forget the argument and --GNU-Debug=dflt)
I guess this is some kind of argument, but I'm not really sure for which
side. :) I agree that expecting errno to remain unchanged across calls
is wrong unless the method/function is documented as preserving errno.
OTOH, if it's convenient to have NSLog preserve errno, I don't think
it's unreasonable to implement and clearly document this.
Printing an incorrect value in a log right after setting errno seems
like a very bad thing, though, and there's no easy fix. You can't
evaluate the arguments early enough in a vararg define. You could
replace the define with a function, but that would change the current
behavior since arguments would be evaluated even if GSDebugSet(...)
isn't set, and avoiding the unconditional evaluation is the only reason
it would have been made a define (if it's supposed to be a performance
optimization, it's broken and should be fixed; fortunately, that case is
easy).
- Alexander Malmberg