• 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: Chris Kane <email@hidden>
  • Date: Thu, 11 Oct 2001 14:18:29 -0700

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:

@implementation A

- init
{
...
b = [[B alloc] initWithA:self];
...
}
@end

@implementation B
- initWithA:(A *) anA
{
...
x = [anA someValue];
...
}
@end

If anA is half-initialized, x's value could be junk. I think
that in that case it is obviously the programmer's
responsibility not to create this kind of coupling or to
order messages so that "it works". Why should the
unarchiving situation be different?

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.

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. 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.

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.


"Erik M. Buck" <email@hidden> wrote:
Cocoa uses the same technique. That is what -awakeFromNib
and -awakeAfterUsingCoder: are for. The -initWithCoder: method should be
implemented to do as little as possible and make few assumptions about the
state of referenced objects. Final initialization based of referenced
objects should take place in an awake method.

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.


Back to Marco:
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. This would be
coherent with all the doc I've seen about alloc and copy,
statements like (in Object Ownership and Disposal): "If you
create an object (using alloc or allocWithZone:) or copy an
object (using copy, copyWithZone:, mutableCopy, or
mutableCopyWithZone:), you alone are responsible for
releasing it. If you didn't directly create or copy the
object, you don't own it and shouldn't release it." This
cannot work if init methods mess with retain counts.

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. 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"];).



Chris Kane
Cocoa Frameworks, Apple


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

  • Prev by Date: Re: NSBitmapImageRep problems
  • Next by Date: Re: NSBitmapImageRep problems
  • 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