• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Memory Management
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Memory Management


  • Subject: Re: Memory Management
  • From: Nat! <email@hidden>
  • Date: Tue, 29 Jul 2003 20:23:50 +0200

Am Dienstag, 29.07.03 um 17:01 Uhr schrieb Marco Scheurer:

On Monday, July 28, 2003, at 09:50 PM, Fritz Anderson wrote:

On Monday, 28 July 2003, at 1:44 PM, Marcel Weiher wrote:

On Monday, Jul 28, 2003, at 01:20 Europe/London, Martin Haecker wrote:
...
- (NSString *)name
{
return [[_name retain] autorelease];
}
Although there has been some championing of this method by well-placed individuals, their preference has not met with an overwhelmingly positive response, to say the least. IMNSHO, their case, although appealing at first, has been thoroughly debunked and is not widely supported by the Cocoa community any longer. Of course, you may disagree with this view, but at the very least the statement that this is the preferred method is highly controversial.

You surprise me. I once ran into a string-processing method in OmniFoundation which, in no-op cases, returned its internal storage. Consider the following code:

NSString * result = [ofProcessingObject processedString];
[ofProcessObject release];
NSLog(@"The result is %@", result);
I am entitled to assume that result has not been disposed-of, am I not?

I share Marcel's views on this subject. We wrote an article which shows why we think that this pattern is a bad thing. It will hopefully be published soon.

This pattern is obviously an attempt to fix in -processedString a problem that is caused by = .

The problem is not caused by =.

In other environments the assignment would prevent result from being freed during the lifetime of the variable. Since it cannot be done here the "solution" is too extend a little bit the lifetime of objects so that it works a little bit more like a garbage collected environment.

This is thinking in another language, and forcing Foundation / Objective-C into that mindframe. It doesn't help putting "garbage collection" as a concept or a goal to be aspired to, into this mail thread.


Now consider the following code:
- doSomething
{
result = [ofProcessObject processedString];
[ofProcessObject release];
[self doSomethingElse];
}

- doSomethingElse
{
NSLog (@"The result is %@", result);
}

Shouldn't I also be able to claim that I am entitled to assume that result has not been disposed-of? Why not? And what about the > following?

- doSomething
{
result = [ofProcessObject processedString];
[ofProcessObject release];
[self performSelector:@selector(doSomethingElse) withObject:nil afterDelay:0.0];
}

- doSomethingElse
{
NSLog (@"The result is %@", result);
}

Obviously, the similarity to a garbage collection is limited. Will everybody stop claiming that result should not have been released in every case?

Autorelease pools have some clear semantics. Every object added to an autorelease pool gains a property, a guaranteed minimum lifetime. Not more not less. Autorelease therefore guarantees (if result is autoreleased) that your case 1 will work and also guarantees that case 2 has a high chance of failure.



I wrote a lot of stuff here <now deleted>, and needed to look up something in the documentation, lo and behold:

http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/ index.html#//apple_ref/doc/uid/10000011i

contains basically everything I wanted to write.


What I'd like to add is this. Sharing a return value between caller and method ideally should be fail safe. To be fail safe the returned value must be under ownership of the caller. With ownership I mean, that the value can be read (or written to, if possible) at the callers convenience.

For those int, double return values it's trivial, because the value is copied through registers or stack. If there is memory involved then there needs to be a clear protocol for the transfer or sharing of that memory. If the memory is owned by the caller, then there is no problem, the caller temporarily grants read/write access to its memory area, and can peruse it at will on return:

- (void) getName:(NSMutableString *) s
{
[s setString:name_];
}

this is ideal and fail safe. It is not done, because it is deemed to cumbersome. The caller must create temporary objects and release them.

If the memory is solely owned by the method (instance), this means a weakening in the fail-safeness

- (NSString *) name
{
return( name_);
}

This transfers a pointer to memory, not owned by the caller. If name_ gets set to something else as a side effect to another call to that instance, I can expect crashes, because the previously returned value might now point to invalid memory. This method provides therefore only a limited kind of read access to the return value. That limited access says, you may access that value, if you know, that it hasn't changed in the mean time. (In 99% of all cases, I think you will be able to say, yes I can do that :), otherwise you'd have problems using NSMutableArrays)

If I code something like this:

- (NSString *) name
{
return( [name_ retain]);
}

I am sharing ownership with the caller. (If name_ is immutable, I am sharing read access completely.) This would be the proper thing to do, alas it is not Foundation like, because the need for the caller to release all accessed objects would also be too painful to code. The Foundation way to achieve almost fail safeness is to provide the caller with [... retain] autorelease] a return value, which gives full read access during the scope of the callers(!) autorelease pool.

The reason why you get these funny problems when name_ is mutable is, because you are not yielding access completely, the contents are still subject to change by the messaged instance. That's why using copy] autorelease] would be proper, as it also gives the full access rights of the return value contents to the caller (within the scope... bla bla).


I am not promoting the use of retain] autorelease] (I dislike slowness :)), but I don't mind it to be the documentation default. What I dislike is the dogmatic "you must code like this". Fortunately I see nothing like this in the Apple dox.

Ciao
Nat!
------------------------------------------------------
But didn't I always tell you, honey, if I just stayed
in place and I never spoke up, good things are bound
to happen ? -- Jonathan Gems
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: Memory Management
      • From: Marcel Weiher <email@hidden>
    • Re: Memory Management
      • From: John Randolph <email@hidden>
    • Re: Memory Management
      • From: Marco Scheurer <email@hidden>
References: 
 >Re: Memory Management (From: Marco Scheurer <email@hidden>)

  • Prev by Date: ScreenSaverEngine and screen saver defaults
  • Next by Date: Beep?
  • Previous by thread: Re: Memory Management
  • Next by thread: Re: Memory Management
  • Index(es):
    • Date
    • Thread