Re: Looping worker threads - NSString vs sprintf
Re: Looping worker threads - NSString vs sprintf
- Subject: Re: Looping worker threads - NSString vs sprintf
- From: Brendan Younger <email@hidden>
- Date: Tue, 31 Jul 2001 13:42:04 -0500
On Tuesday, July 31, 2001, at 02:36 AM, Ondra Cada wrote:
>
Brendan,
>
>
looks to me like you use a quite different API than me???
>
>
>>>>>> Brendan Younger (BY) wrote at Mon, 30 Jul 2001 19:33:06 -0500:
>
BY> - (NSString*)string
>
BY> {
>
BY> return [somestring retain];
>
BY> }
>
>
Such an implementation is *DEFINITELY* a bad Cocoa citizen, and almost
>
surely will cause memory leaks.
It will only cause memory leaks if you use it for returning values to a
NS* object. If you're using the class solely for internal use and you
*know* that the object will be retained it can most certainly be coded
correctly. Think of it this way, this is what we would all be doing if
-autorelease didn't exist, and that is sort of what Christian Mike
implied. (More on this later.)
>
>
BY> - (void)someMethod
>
BY> {
>
BY> NSString *temp = [SomeClass string];
>
BY>
>
BY> ...use temp here...
>
BY>
>
BY> [temp release];
>
BY> }
>
>
The proper way to do this is
>
>
-(NSString*)string { return somestring; }
>
// or
>
-(NSString*)string { return [NSString stringWith....]; }
>
// or
>
-(NSString*)string { return [[[NSString alloc] initWith...]
>
autorelease]; }
>
>
-(void)someMethod {
>
NSString *temp=[[SomeClass string] retain]; // if needed at
>
all--generally not!
>
...
>
[temp release];
>
}
>
>
BY> This too is prone to error but may be effective when you cannot
>
count
>
BY> on -autorelease ever doing its job.
>
>
I've yet to see situation when you can't count on autorelease; could you
>
please add an example?
Christian Mike's original post said this: that some of his code "never
returns to any
type of outer run loop." You can read this two ways. That his code
never returns to something like an NSRunLoop but that it does always go
through his own polling while(true) { . . . } loop or that the code is
inherently nonlinear (sort of like an interrupt handler) whereby there
is absolutely *no* common loop or code on which to pin an autorelease
pool. Both cases are possible which is why I started out with the
autorelease pool-attached-to-the-polling-loop example and went on to
what one could do if the second case were true.
>
>
BY> But best of all would be to avoid ObjC objects as much as
>
possible. For
>
>
Worst of all, IMHO, but of course you _can_ design apps without them if
>
you
>
prefer to. I, for one, don't want to dispense with the power and
>
flexibility
>
of the Foundation Kit.
>
I would be one of the first to defend the power and flexibility and
all-around usefulness of the Cocoa classes but in this case, it sounds
very much as though he already has the functionality that he needs and
it would be best from a time/efficiency standpoint to avoid replacing
existing functionality with Cocoa classes since his code is not firmly
based in the Cocoa run loop/memory handling model.
>
BY> As for the C I/O routines, they don't use ObjC at all, why should
>
they
>
BY> create memory leaks?
>
>
Well, perhaps since it is much easier to overlook a memory buffer, since
>
autorelease pools can't be used for it? ;)
>
Once again, the code is already there. We assume it works.
>
BY> And about the setjmp/longjmp, yes they will mess everything up.
>
Badly.
>
>
Why should they do that? I admit I've never tried them in OS X, but
>
unless
>
Apple reimplemented the exceptions quite strangely, there should be no
>
problem at all. I did use setjmps/longjmps in NeXTStep/OpenStep without
>
any
>
problems once or twice (generally it proved more convenient to rewrite
>
the
>
stuff to exceptions).
>
NSExeceptions are indeed implemented using setjmp/longjmp however, they
cause memory leaks since (I believe) calling longjmp causes your
function to fall through which means any classes you've instantiated and
were planning on releasing since setjmp will be dangling there. This is
often not so bad when raising an exception since your program will
probably quit itself soon anyway, but Christian Mike implied that he
used them to stay away from things like endless recursion and
overflowing the stack. That's fine if all you have are stack-based
variables but will cause memory leaks if you've malloc'd something or
instantiated a class.
>
BY> Find a way to get rid of them or create a new class of which there
>
is
>
BY> only one of for each thread and register each ObjC class that's
>
created
>
BY> with it and unregister the class when it's released....
>
>
Why should anyone implement his own autorelease pool if there's one,
>
which
>
works well, and is *THOROUGHLY* tested already?!?
>
I concede this one. In some of the stranger scenarios I was thinking
of, I thought that the ability to unregister objects was necessary, but
I was mistaken. It *is* necessary, though, to work *only* with
autoreleased objects (excluding ivars of course) if you are going to
have unpredictable, nonfatal setjmp/longjmp calls. For example, this is
a no-no:
void SomeFunc()
{
SomeObj* obj = [[SomeObj alloc] init];
...do stuff here...
[obj release];
}
This is bad because "do stuff here" may very well be a longjmp call.
Also, with a nonlinear program design, the autorelease pool must be a
global variable and must be emptied at more or less random times, but
this can be done as long as you immediately re-instanciate it.
>
BY> Whatever you decide to do, good luck.
>
>
This is about the only thing from your mail I can agree with ;)
>
Whew, glad we found some middle ground.
Brendan Younger