• 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: half-initialized objects during decoding (Re: Persistance)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: half-initialized objects during decoding (Re: Persistance)


  • Subject: Re: half-initialized objects during decoding (Re: Persistance)
  • From: Marco Scheurer <email@hidden>
  • Date: Fri, 12 Oct 2001 11:52:33 +0200

On Thursday, October 11, 2001, at 11:18 pm, Chris Kane wrote:

On Thursday, October 11, 2001, at 05:47 AM, Marco Scheurer wrote:
On Wed, 10 Oct 2001 13:21:01 -0700
Chris Kane <email@hidden> wrote:
The 'half-initialized object' problems I was referring to
I describe below. [...]

It seems to me that you can force yourself into the same
situation in other cases:
[...]

This is true. However, it's more common to be receiving half-initialized objects back from the unarchiver than to get them passed in as parameters in the ordinary course of executing the program.

Why?

It's interesting to think about fixing this because it is hard to detect that it is going on, as well -- there's no way to detect that the object you've gotten back from -decodeObject is done initializing, today.

Maybe a solution then would be to make it easier to detect the problem. Maybe something like assertions that could be turned on or off, even though bracketing initWithCoder methods in initDidStart / initDidFinish could be cumbersome.

Since the returned object from that method is autoreleased, it is natural to want to send it -retain, if nothing else, but even that may not be safe. Particularly when the cycle involves more than two nodes/levels in the object graph, it can be quite a mysterious problem.

I still think it could be safe by initializing the retain count before anything else. Just something one needs to be aware. Surely, this kind of temporal coupling is not great, but it happens.

On the other hand, there are several such issues of this general nature (cyclic +initialize methods is another one that bites people) that don't have solutions other than the programmer rewriting to avoid the problem. If we could fix it while we're changing the general coding mechanism, or by suggesting a strategy developers should use when modifying their encode/decode methods to take advantage of the named values anyway (though you obviously won't have to do that), then that would be nice.

I'm still unconvinced that a solution is needed, especially if it involves trade offs in performance, or if the cure is worse than the problem and would make writing initWithCoder a pain, as you suggested in a previous message.

In the current NSUnarchiver,
1) -awakeAfterUsingCoder: is called immediately after -initWithCoder:, to allow awakeAfterUsingCoder: to substitute a new object; nothing in the middle of being unarchived, except the object receiving -awakeAfterUsingCoder:, is any more initialized in -awakeAfterUsingCoder: than it was in -initWithCoder:.
2) -awakeAfterUsingCoder: doesn't have access to all the encoded object state that -initWithCoder: had; -initWithCoder: has consumed some of it, which it may need to save for -awakeAfterUsingCoder: in some cases, even if the state will eventually be thrown away (in cases where some actual state of an object is synthesized from the encoded state, which is quite common when dealing with old archived versions backwards compatibly); this is awkward, but not the end of the world.


And, none of this discussion addresses the fact that although -initWithCoder: and -awakeAfterUsingCoder: return id, and in theory allow you to return a different instance, in practice you may well break references that other classes of objects have to instances of yours if you do so. There isn't much those other classes can do about the actions of your class (and this applies to developers using Cocoa classes which are returning different objects too). Delaying the -awakeAfterUsingCoder:, like -awakeFromNib is, until the main decoding is all done, would just exacerbate the replacement problem (if it continued to return id and not void like -awakeFromNib). The capability of replacement could be eliminated altogether; however, replacement is a compelling feature -- people want to do that.

Replacement can also be done in other init methods, so again the problem is general.


I would have imagined that initializing a retain count (to 1
rather than 0) should be left to allocWithZone, and that
init... methods should leave it untouched. [...]
Some of this has already been addressed by other mail. One of the reasons for the +alloc/-init split is that, in some 'pure' OO sense, class methods should not be fiddling with the internal data of class instances.

I agree, and it is a very valuable pattern. However this is not what is done in the default case, NSObject:

NSLog (@"%d", [[NSObject alloc] retainCount]);

prints "1".

Of course, in the case of NSObject (implementation detail) the retain count is not stored in the object's data, but nevertheless, it is alloc, not init that initializes the retain count. All this can be considered irrelevant because:

Plus, I think you're taking the doc a bit too literally here -- they're saying "alloc or allocWithZone:", but a paired initializer with those is also assumed, and is the thing which does the actual initialization. "alloc or allocWithZone:" are mentioned because those are the markers you'd see in your code to indicate that a retain is coming back (as opposed to an expression like: [NSString stringWithCString:"foo"];).

Right, I also mentionned that in a previous message.

Marco Scheurer
Sen:te, Lausanne, Switzerland http://www.sente.ch


  • Follow-Ups:
    • Re: half-initialized objects during decoding (Re: Persistance)
      • From: Chris Kane <email@hidden>
References: 
 >Re: half-initialized objects during decoding (Re: Persistance) (From: Chris Kane <email@hidden>)

  • Prev by Date: Re: Aliases & fileAttributesAtPath:
  • Next by Date: Re: Aliases & fileAttributesAtPath:
  • Previous by thread: Re: half-initialized objects during decoding (Re: Persistance)
  • Next by thread: Re: half-initialized objects during decoding (Re: Persistance)
  • Index(es):
    • Date
    • Thread