@property problem

  • So, I'm trying to be a good little Obj-C 2.0 programmer and use these
    newfangled properties.  Xcode doesn't seem to appreciate my attempts.

    I've boiled the problem down to this snippet:

    @interface MyWindow : NSWindow
    {
    }
    @property(readwrite) BOOL    capturing;

    @end

    @implementation MyWindow

    @synthesize capturing;

    @end

    When I compile that, I get the error:

    error: synthesized property 'capturing' must either be named the same
    as a compatible ivar or must explicitly name an ivar

    AFAICT, "capturing" IS the name of my ivar.  What is it *really*
    complaining about?  What did I do wrong?

    Thanks!
    randy
  • Properties don't allocate storage, they simply provide a mechanism for
    accessing it.

    You need to declare your ivar somewhere:

    @interface MyWindow : NSWindow
    {
    id capturing;
    }

    +Melissa

    On Feb 11, 2008, at 13:14, Randall Meadows wrote:

    > So, I'm trying to be a good little Obj-C 2.0 programmer and use
    > these newfangled properties.  Xcode doesn't seem to appreciate my
    > attempts.
    >
    > I've boiled the problem down to this snippet:
    >
    > @interface MyWindow : NSWindow
    > {
    > }
    > @property(readwrite) BOOL    capturing;
    >
    > @end
    >
    > @implementation MyWindow
    >
    > @synthesize capturing;
    >
    > @end
    >
    > When I compile that, I get the error:
    >
    > error: synthesized property 'capturing' must either be named the
    > same as a compatible ivar or must explicitly name an ivar
    >
    > AFAICT, "capturing" IS the name of my ivar.  What is it *really*
    > complaining about?  What did I do wrong?
    >
    >
    > Thanks!
    > randy
  • On 2/11/08, Randall Meadows <cocoa-dev...> wrote:
    > AFAICT, "capturing" IS the name of my ivar.  What is it *really*
    > complaining about?  What did I do wrong?

    You are incorrect.  Re-read the documentation closely; on 32-bit
    architectures (the "non-fragile instance variable runtime") you must
    provide an instance variable for your property.  If it does not have
    the same name as the property, you must specify this in your
    declaration.

    On 64-bit architectures, you can omit the ivar declaration.

    Also, you have not specified a memory management method in your
    @property declaration, which you must do if you are not using garbage
    collection.

    HTH,
    --Kyle Sluder
  • > I've boiled the problem down to this snippet:
    >
    > @interface MyWindow : NSWindow
    > {
    > }
    > @property(readwrite) BOOL    capturing;
    ...
    > error: synthesized property 'capturing' must either be named the
    > same as a compatible ivar or must explicitly name an ivar

    You haven't declared a compatible ivar named "capturing". You'd need
    to do something like this:

    @interface MyWindow : NSWindow
    {
    BOOL capturing;  // <-- here!
    }
    @property(readwrite) BOOL    capturing;

    The line marked above declared an ivar with the same name and the same
    type as your property declaration, so now synthesize will be able to
    do its thing.

    Obj-C *can* be smart enough to generate this ivar for you behind the
    scenes, but only if you're using the 64bit runtime. If you don't
    require 32bit compatibility, turn it off, and then you don't have to
    worry about declaring these ivars for synthesize.

    Cheers,
    -Joshua Emmons
  • On Feb 11, 2008 1:27 PM, Melissa J. Turner <mjturner...> wrote:
    > Properties don't allocate storage, they simply provide a mechanism for
    > accessing it.

    They can allocate storage.

    Review: <http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articl
    es/chapter_5_section_8.html#//apple_ref/doc/uid/TP30001163-CH17-SW3
    >

    -Shawn
  • On Feb 11, 2008, at 1:27 PM, Melissa J. Turner wrote:

    > You need to declare your ivar somewhere:
    >
    > @interface MyWindow : NSWindow
    > {
    > id capturing;
    > }

    ...or in this particular case:

    @interface MyWindow : NSWindow
    {
    BOOL capturing;
    }

    j o a r
  • On Feb 11, 2008, at 16:28, Kyle Sluder wrote:

    > Also, you have not specified a memory management method in your
    > @property declaration, which you must do if you are not using garbage
    > collection.

    It defaults to "assign." Declaring that for a BOOL would be
    (unnecessarily) redundant.

    /brian
  • A big THANKS to all of you who responded so quickly to point out my
    absent-mindedness of not actually *declaring* my "capturing" ivar.  I
    can't tell you how many times I overlooked that simple fact when I was
    comparing my code to the sample code in the ObjC 2.0 docs.

    Please consider me sufficiently flogged for being a bonehead.  (No
    actual noodles were harmed.)

    On Feb 11, 2008, at 2:14 PM, Randall Meadows wrote:

    > So, I'm trying to be a good little Obj-C 2.0 programmer and use
    > these newfangled properties.  Xcode doesn't seem to appreciate my
    > attempts.
    >
    > I've boiled the problem down to this snippet:
    >
    > @interface MyWindow : NSWindow
    > {
    > }
    > @property(readwrite) BOOL    capturing;
    >
    > @end
    >
    > @implementation MyWindow
    >
    > @synthesize capturing;
    >
    > @end
    >
    > When I compile that, I get the error:
    >
    > error: synthesized property 'capturing' must either be named the
    > same as a compatible ivar or must explicitly name an ivar
    >
    > AFAICT, "capturing" IS the name of my ivar.  What is it *really*
    > complaining about?  What did I do wrong?
  • FYI: The property name doesn't have to match the instance variable
    name, so it's OK to keep using prefixes on your ivar names. So you
    could declare the class as

    @interface MyWindow : NSWindow {
    BOOL _capturing;  // or mCapturing or whatever
    }
    @property(readwrite) BOOL    capturing;
    @end

    and then in the implementation use
    @synthesize capturing=_capturing;

    I strongly recommend prefixing all instance variables, to avoid
    confusion with locals. I've also found out the hard way that it's even
    more important to do this with properties.

    Not prefixing property instance vars can lead to a type of mistake
    where, in the implementation of the same class, you accidentally write
    something like
    contents = [NSArray array];
    when you meant to write
    self.contents = [NSArray array];
    Do you see the problem? Assuming no GC, and the 'contents' property is
    marked 'retain' or 'copy', the first line will cause a crash sometime
    later on, because you directly assigned an autoreleased value to an
    instance variable, so sometime after this method leaves scope, that
    array is going to be dealloced and 'contents' will be a bad pointer.
    The second line invokes the property's setter method, which correctly
    retains or copies the array.

    —Jens

    PS: To forstall an FAQ: Yes, it is kosher to use "_" as your ivar
    prefix, even though the Foundation and AppKit classes do the same.
    Name collisions are not a problem. It is, however, recommended to not
    use "_" as a method name prefix, because you can collide with and
    accidentally override internal superclass methods.
  • On 2/11/08, Brian Christensen <brian...> wrote:
    > On Feb 11, 2008, at 16:28, Kyle Sluder wrote:
    >
    >> Also, you have not specified a memory management method in your
    >> @property declaration, which you must do if you are not using garbage
    >> collection.
    >
    > It defaults to "assign." Declaring that for a BOOL would be
    > (unnecessarily) redundant.

    Not true for non-GC code (which is what I specified).  The compiler
    will issue a warning if you do not explicitly declare a memory
    management model, because "This encourages you think about what memory
    management behavior you want and type it explicitly."  (From
    http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articl
    es/chapter_5_section_3.html#//apple_ref/doc/uid/TP30001163-CH17-SW2

    ).

    --Kyle Sluder
  • On Feb 11, 2008, at 2:32 PM, Kyle Sluder wrote:

    >>> Also, you have not specified a memory management method in your
    >>> @property declaration, which you must do if you are not using
    >>> garbage
    >>> collection.
    >>
    >> It defaults to "assign." Declaring that for a BOOL would be
    >> (unnecessarily) redundant.
    >
    > Not true for non-GC code (which is what I specified).  The compiler
    > will issue a warning if you do not explicitly declare a memory
    > management model

    It will only issue a warning for object properties, not for non-object
    properties.

    j o a r
  • Is there any performance penalty for using the 64 bit runtime?  In
    general what are the disadvantages of disabling 32 bit compatibility
    other than the obvious fact that my program wouldn't run on 32 bit
    machines?

    On Feb 11, 2008, at 4:29 PM, Joshua Emmons wrote:
    > Obj-C *can* be smart enough to generate this ivar for you behind the
    > scenes, but only if you're using the 64bit runtime. If you don't
    > require 32bit compatibility, turn it off, and then you don't have to
    > worry about declaring these ivars for synthesize.
  • On Feb 11, 2008, at 3:33 PM, Adam P Jenkins wrote:
    > Is there any performance penalty for using the 64 bit runtime?  In
    > general what are the disadvantages of disabling 32 bit compatibility
    > other than the obvious fact that my program wouldn't run on 32 bit
    > machines?

    If you are the first 64 bit app launched on the system, there will be
    a slightly performance penalty as all of the 64 bit versions of the
    various dylibs are mapped into memory.

    Obviously, you can't deploy a 64 bit application to 32 bit only macs;
    the performance is infinitely bad, in that case. :)

    The performance characteristics of Objective-C changes slightly in 64
    bit.  Message dispatch and instance variable access changes
    slightly.  It is unlikely that this will change application
    performance significantly.

    The 64 bit ABI also features a unified ObjC/C++ exception model.  It
    is often called "zero cost".  This is not really true;  it simply
    shifts the expense related to exception handling from the setup of the
    handler to when an exception is actually thrown.  It can have a huge
    [positive] impact on your application's performance if you have lots
    and lots of exception handlers but few exceptions are ever thrown.

    Of course, your memory footprint will be slightly larger in that
    everything that is pointer sized will be doubled in size.  This is
    both a direct and indirect impact in that some structures may have a
    bit more padding to ensure correct alignment for pointers.

    The Garbage Collector works just fine in 64 bits.

    b.bum
  • > Is there any performance penalty for using the 64 bit runtime?  In
    > general what are the disadvantages of disabling 32 bit compatibility
    > other than the obvious fact that my program wouldn't run on 32 bit
    > machines?

    By default on Leopard only 32-bit apps run, so you only have the 32-
    bit versions of libraries loaded.  When the first 64-bit Cocoa app
    runs, that's a lot of libraries that need to be loaded...  I don't
    know what the increase in memory usage is quantitatively, but afaik
    it's non-trivial.

    This has been discussed in detail on a mailing list before, at some
    point, but I can't find it in the archives or via Google.. :/

    Wade
  • On 2/11/08, j o a r <joar...> wrote:
    > It will only issue a warning for object properties, not for non-object
    > properties.

    Once again, devil, meet details.

    --Kyle Sluder
  • On Feb 11, 2008 AD, at 4:33 PM, Adam P Jenkins wrote:

    > Is there any performance penalty for using the 64 bit runtime?  In
    > general what are the disadvantages of disabling 32 bit compatibility
    > other than the obvious fact that my program wouldn't run on 32 bit
    > machines?

    The 32-bit frameworks and libraries are around a decade old; the 64-
    bit frameworks and libraries are essentially at version 1.0 and are
    nowhere near as mature. As a result, they have some interesting bugs
    that don't exist in the 32-bit frameworks. I've filed them as I've
    found them...

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On Intel, 64-bit code supposedly runs somewhat faster, as it uses a
    different instruction set with considerably more registers available.
    (The regular x86 has only four registers, IIRC. Or maybe that was the
    Z80.) On PowerPC, the G5 uses the same instruction set in 64-bit, so
    it doesn't make a difference.

    Of course, 64-bit code uses more memory for pointers, which increases
    cache misses and paging, so whether it's actually faster probably
    depends on exactly what the code does...

    —Jens
  • On 11 Feb 08, at 19:44, Jens Alfke wrote:
    > On Intel, 64-bit code supposedly runs somewhat faster, as it uses a
    > different instruction set with considerably more registers
    > available. (The regular x86 has only four registers, IIRC. Or maybe
    > that was the Z80.) On PowerPC, the G5 uses the same instruction set
    > in 64-bit, so it doesn't make a difference.

    32-bit x86 has eight registers: eax, ebx, ecx, edx, esi, edi, ebp, and
    esp. (The last two are basically reserved, though.) x86-64 has sixteen
    registers.
  • On 2/11/08 2:11 PM, Jens Alfke said:

    > PS: To forstall an FAQ: Yes, it is kosher to use "_" as your ivar
    > prefix, even though the Foundation and AppKit classes do the same.
    > Name collisions are not a problem.

    Could you elaborate?  If I subclass NSView and add an ivar named
    "_sisterView" then in some future SDK NSView.h also gets a _sisterView
    ivar, wouldn't there be a compiler error?  If only Apple uses the
    underscore prefix and I don't, then there will be no conflicts.

    Pity private ivars have to be in public headers...

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • On Feb 12, 2008, at 7:58 AM, Sean McBride wrote:

    >> PS: To forstall an FAQ: Yes, it is kosher to use "_" as your ivar
    >> prefix, even though the Foundation and AppKit classes do the same.
    >> Name collisions are not a problem.
    >
    > Could you elaborate?  If I subclass NSView and add an ivar named
    > "_sisterView" then in some future SDK NSView.h also gets a _sisterView
    > ivar, wouldn't there be a compiler error?

    Yes, and that's why I believe Jens is telling you that it's OK to use
    the same prefix for ivars as anyone else that you're sharing code
    with: Because any name clashes would be immediately apparent. This in
    contrast to, for example, method names.

    > Pity private ivars have to be in public headers...

    Agreed, that is truly a pity.

    j o a r
  • On 12 Feb '08, at 7:58 AM, Sean McBride wrote:

    > Could you elaborate?  If I subclass NSView and add an ivar named
    > "_sisterView" then in some future SDK NSView.h also gets a _sisterView
    > ivar, wouldn't there be a compiler error?

    Yes, but not a runtime error, and it wouldn't break binary
    compatibility. So it wouldn't affect users, only you (or other people
    using your source code), and it's easy to fix with a quick Refactor
    command.

    Unlike a method-name conflict, which _would_ break existing binary
    copies of your app, in strange and hard-to-predict ways.

    —Jens
  • > Yes, and that's why I believe Jens is telling you that it's OK to
    > use the same prefix for ivars as anyone else that you're sharing
    > code with: Because any name clashes would be immediately apparent.
    > This in contrast to, for example, method names.

    Note that this isn't true in the 64-bit runtime, where ivars don't
    have to be declared publicly.  There, AFAIK, ivars are uniqued by name
    still, so unexpected clashes are possible (and wouldn't be detected at
    compile time, necessarily... someone less lazy than me should write
    some test cases and find out :) ).

    Wade
  • Okay, but why the diff? Why should it matter whether you're using 32
    or 64 bits? Storage is still storage, and it seems you'd still need
    to provide that storage even under a 64-bit runtime.

    On Feb 11, 2008, at 3:29 PM, Joshua Emmons wrote:

    >> I've boiled the problem down to this snippet:
    >>
    >> @interface MyWindow : NSWindow
    >> {
    >> }
    >> @property(readwrite) BOOL    capturing;
    > ...
    >> error: synthesized property 'capturing' must either be named the
    >> same as a compatible ivar or must explicitly name an ivar
    >
    > You haven't declared a compatible ivar named "capturing". You'd
    > need to do something like this:
    >
    > @interface MyWindow : NSWindow
    > {
    > BOOL capturing;  // <-- here!
    > }
    > @property(readwrite) BOOL    capturing;
    >
    > The line marked above declared an ivar with the same name and the
    > same type as your property declaration, so now synthesize will be
    > able to do its thing.
    >
    > Obj-C *can* be smart enough to generate this ivar for you behind
    > the scenes, but only if you're using the 64bit runtime. If you
    > don't require 32bit compatibility, turn it off, and then you don't
    > have to worry about declaring these ivars for synthesize.
    >
    >
    > Cheers,
    > -Joshua Emmons
  • Because changing the 32 bits runtime to support this kind of feature
    would have break binary compatibility with previous version, and
    previous applications.
    This is the same for "zero-cost" exceptions that works with 64 bits
    applications, but not with 32 bits applications.
    And it is also the case for the fragile ivar problem that was solve in
    the 64 bits runtime.

    Le 16 févr. 08 à 23:35, William Squires a écrit :

    > Okay, but why the diff? Why should it matter whether you're using 32
    > or 64 bits? Storage is still storage, and it seems you'd still need
    > to provide that storage even under a 64-bit runtime.
    >
    > On Feb 11, 2008, at 3:29 PM, Joshua Emmons wrote:
    >
    >>> I've boiled the problem down to this snippet:
    >>>
    >>> @interface MyWindow : NSWindow
    >>> {
    >>> }
    >>> @property(readwrite) BOOL    capturing;
    >> ...
    >>> error: synthesized property 'capturing' must either be named the
    >>> same as a compatible ivar or must explicitly name an ivar
    >>
    >> You haven't declared a compatible ivar named "capturing". You'd
    >> need to do something like this:
    >>
    >> @interface MyWindow : NSWindow
    >> {
    >> BOOL capturing;  // <-- here!
    >> }
    >> @property(readwrite) BOOL    capturing;
    >>
    >> The line marked above declared an ivar with the same name and the
    >> same type as your property declaration, so now synthesize will be
    >> able to do its thing.
    >>
    >> Obj-C *can* be smart enough to generate this ivar for you behind
    >> the scenes, but only if you're using the 64bit runtime. If you
    >> don't require 32bit compatibility, turn it off, and then you don't
    >> have to worry about declaring these ivars for synthesize.
    >>
    >>
    >> Cheers,
    >> -Joshua Emmons

    >
  • But it doesn't answer the question. Why even make the change in
    the 64-bit runtime? This would seem to hide a source of bugs, by
    taking the responsibility for providing storage away from the
    programmer. Some storage is still necessary. And besides, in order to
    take advantage of Leopard features like this one (whether on PPC or
    Intel), you should still have to link against the 10.5 SDK, so it
    would seem more reasonable to make the update to both the 32 and 64-
    bit runtimes, but only in the 10.5 SDK. Then you could update the
    10.5 SDK (to 10.5.1) to allow for this "syntactic sugar" under both
    32- and 64-bit.
      I mean, after all, all it means is that you're changing the
    default size of an (Integer) register in the CPU chip, and updating
    the OS to take advantage. How would this make implementing (or not
    implementing) this change any harder or easier?

    On Feb 16, 2008, at 6:03 PM, Jean-Daniel Dupas wrote:

    > Because changing the 32 bits runtime to support this kind of
    > feature would have break binary compatibility with previous
    > version, and previous applications.
    > This is the same for "zero-cost" exceptions that works with 64 bits
    > applications, but not with 32 bits applications.
    > And it is also the case for the fragile ivar problem that was solve
    > in the 64 bits runtime.
    >
    > Le 16 févr. 08 à 23:35, William Squires a écrit :
    >
    >> Okay, but why the diff? Why should it matter whether you're using
    >> 32 or 64 bits? Storage is still storage, and it seems you'd still
    >> need to provide that storage even under a 64-bit runtime.
    >>
    >> On Feb 11, 2008, at 3:29 PM, Joshua Emmons wrote:
    >>
    >>>> I've boiled the problem down to this snippet:
    >>>>
    >>>> @interface MyWindow : NSWindow
    >>>> {
    >>>> }
    >>>> @property(readwrite) BOOL    capturing;
    >>> ...
    >>>> error: synthesized property 'capturing' must either be named the
    >>>> same as a compatible ivar or must explicitly name an ivar
    >>>
    >>> You haven't declared a compatible ivar named "capturing". You'd
    >>> need to do something like this:
    >>>
    >>> @interface MyWindow : NSWindow
    >>> {
    >>> BOOL capturing;  // <-- here!
    >>> }
    >>> @property(readwrite) BOOL    capturing;
    >>>
    >>> The line marked above declared an ivar with the same name and the
    >>> same type as your property declaration, so now synthesize will be
    >>> able to do its thing.
    >>>
    >>> Obj-C *can* be smart enough to generate this ivar for you behind
    >>> the scenes, but only if you're using the 64bit runtime. If you
    >>> don't require 32bit compatibility, turn it off, and then you
    >>> don't have to worry about declaring these ivars for synthesize.
    >>>
    >>>
    >>> Cheers,
    >>> -Joshua Emmons

    >>
  • On Feb 17, 2008, at 10:59 AM, William Squires wrote:

    > But it doesn't answer the question. Why even make the change in the
    > 64-bit runtime? This would seem to hide a source of bugs, by taking
    > the responsibility for providing storage away from the programmer.
    > Some storage is still necessary. And besides, in order to take
    > advantage of Leopard features like this one (whether on PPC or
    > Intel), you should still have to link against the 10.5 SDK, so it
    > would seem more reasonable to make the update to both the 32 and 64-
    > bit runtimes, but only in the 10.5 SDK. Then you could update the
    > 10.5 SDK (to 10.5.1) to allow for this "syntactic sugar" under both
    > 32- and 64-bit.
    > I mean, after all, all it means is that you're changing the default
    > size of an (Integer) register in the CPU chip, and updating the OS
    > to take advantage. How would this make implementing (or not
    > implementing) this change any harder or easier?

    One thing to remember is that if you were to do this, you would need
    another entire copy of all the system frameworks - one for the 32 bit
    "compatibility" version (for apps linked with 10.4) and another for
    the new features that you'd get with linked-with-10.5 apps.

    This may not seem like much (since disks are cheap, though we are
    talking a lot of space - and going from 1 to 2 DVDs to install Leopard
    would be a non-trivial impact) but all of these frameworks get loaded
    into memory as well.  For example, turn on activity monitor and look
    at memory usage once you launch your first 64 bit app.  See the nice
    big jump in used memory?  That's the 64 bit apps, and for now, there
    aren't a lot of 64 bit apps out there to make this a problem (and they
    tend to be targeted to markets that have lots of memory installed,
    etc..).

    If this sort of memory usage were to be hit when using "common level"
    apps, the whole user experience of OS X would go down.

    Not to mention that having to QA system updates with yet-another-
    version of the frameworks makes things uglier as well (right now its 2
    CPUs x [32 bit + 64 bit + 64 bit GC] which would become 2 CPUs x [32
    bit 10.4 + 32 bit 10.5 + 32 bit 10.5 GC + 64 bit + 64 bit GC] - 6 vs
    10 testing configuration).  There are more than purely technical
    decisions involved in shipping products.

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium | prime : build, mutate, evolve, animate : the next
    generation of fractal art
  • On Feb 17, 2008, at 8:59 AM, William Squires wrote:
    > But it doesn't answer the question. Why even make the change in the
    > 64-bit runtime? This would seem to hide a source of bugs, by taking
    > the responsibility for providing storage away from the programmer.
    > Some storage is still necessary. And besides, in order to take
    > advantage of Leopard features like this one (whether on PPC or
    > Intel), you should still have to link against the 10.5 SDK, so it
    > would seem more reasonable to make the update to both the 32 and 64-
    > bit runtimes, but only in the 10.5 SDK. Then you could update the
    > 10.5 SDK (to 10.5.1) to allow for this "syntactic sugar" under both
    > 32- and 64-bit.
    > I mean, after all, all it means is that you're changing the default
    > size of an (Integer) register in the CPU chip, and updating the OS
    > to take advantage. How would this make implementing (or not
    > implementing) this change any harder or easier?

    Apple does not ship the Tiger version of the frameworks and runtime
    with Leopard.  All of the frameworks/dylibs on Leopard, while they
    contain Leopard specific features, maintain backwards compatibility
    with prior releases of the OS.

    The changes required to support the various Modern Runtime features
    found in the 64 bit version of the Leopard runtime would have required
    ABI changes -- changes to the way the compiler generates code, call
    sites and/or metadata -- to support.  That is, it isn't just
    syntactic sugar -- it changes the way Objective-C classes are
    represented both in the executable and in memory.

    Making a change to the ABI would break all applications that were
    compiled for the old ABI.

    Or it would require that Apple ship two entire copies of all
    frameworks/dylibs on the system;  one compiled with the 10.5 ABI and
    one compiled with the 10.4-and-prior ABI.

    b.bum
  • On Feb 17, 2008, at 11:59 AM, William Squires wrote:

    > But it doesn't answer the question. Why even make the change in the
    > 64-bit runtime? This would seem to hide a source of bugs, by taking
    > the responsibility for providing storage away from the programmer.
    > Some storage is still necessary.

    As it stands, you cannot add iVars to a base class in the 32-bit
    runtime without required that all subclasses be recompiled.

    This is particularly important for frameworks like AppKit. An AppKit
    class cannot have an iVar added to it because it would break binary
    compatibility with everyone who subclassed it. The 64-bit runtime
    solves this problem.

    > And besides, in order to take advantage of Leopard features like
    > this one (whether on PPC or Intel), you should still have to link
    > against the 10.5 SDK, so it would seem more reasonable to make the
    > update to both the 32 and 64-bit runtimes, but only in the 10.5 SDK.
    > Then you could update the 10.5 SDK (to 10.5.1) to allow for this
    > "syntactic sugar" under both 32- and 64-bit.
    > I mean, after all, all it means is that you're changing the default
    > size of an (Integer) register in the CPU chip, and updating the OS
    > to take advantage. How would this make implementing (or not
    > implementing) this change any harder or easier?

    The 32-bit runtime must remain binary compatible with all code that
    was compiled and targeted for Tiger and earlier.

    It is extremely desirable to be able to link against the 10.5 SDK and
    still deploy your application on Tiger (after taking appropriate
    measures.)

    By restricting this changes to the 64-bit runtime, all binary
    compatibility issues are avoided, because there are no legacy 64-bit
    applications.

    Jim
  • On Feb 17, 2008, at 11:13 AM, Jim Correia wrote:

    > On Feb 17, 2008, at 11:59 AM, William Squires wrote:
    >
    >> But it doesn't answer the question. Why even make the change in
    >> the 64-bit runtime? This would seem to hide a source of bugs, by
    >> taking the responsibility for providing storage away from the
    >> programmer. Some storage is still necessary.
    >
    > As it stands, you cannot add iVars to a base class in the 32-bit
    > runtime without required that all subclasses be recompiled.
      ??? Why should the subclasses know anything about the base class
    other than what the base class exposes in its API (from the POV of
    whomever is writing the subclass code, if they follow proper OO
    methodologies)? Only if I rewrite the subclass to specifically use
    the new iVar should I need to recompile it.
      i.e. If I have a base class A

    @interface

    class MyObject : NSObject <- Yeah, I know this isn't needed, just
    there 'cause I'm retentive :)
      {
      int iMyIVar;
      }

    - (id) init;
    - (void) printMe;
    - (int) myIVar;
    - (void) setMyIVar: (int) i;

    @end

    and I make another class B that inherits from it, then if I only use
    this API (by #import "MyObject.h") in my code, I should be okay even
    if someone adds a new property or method, since my code doesn't even
    look at the new stuff. That is, if I do:

    ...
    {
    MyObject *myObj = [[MyObject alloc] init];

    ...
    }

    somwehere, then *myObj points to some data structure in memory (a C
    struct) that contains the iVars, and a "smart" pointer to the method
    implementations I can reach via the API (i.e. the public '-' methods
    in the @interface section). So all my class B cares about is that a
    "MySubObject *" points to a data structure, one of whose elements
    (iVars) is "iMyIVar" of type (int) (because it's inherited from
    MyObject), and that I can get to not only my methods, but any
    inherited methods through the "smart" pointer in that data structure.
      And really, I shouldn't even access the "iMyIVar" in the subclass
    except through the inherited accessors (getters/setters), so I
    shouldn't even need to know what iVars are in the base class, just
    the accessors for them (which are methods.) So even if Apple's
    software engineers decide to add an iVar to some NS framework class
    (or class cluster), I shouldn't care unless I want to look at the
    documentation to see what new methods (including accessors) are
    available in that class. Then I'd have to recompile my subclass in
    any event because I changed the code.
      Right?
      Now it'd be different if the REMOVED a method - that would be bad
    mojo! :(

    > This is particularly important for frameworks like AppKit. An
    > AppKit class cannot have an iVar added to it because it would break
    > binary compatibility with everyone who subclassed it. The 64-bit
    > runtime solves this problem.
    >
    How? And, more importantly, why? What advantage is added by hiding
    the need for the storage? And what happens if you follow the older
    model and still provide the storage anyway?

    >> And besides, in order to take advantage of Leopard features like
    >> this one (whether on PPC or Intel), you should still have to link
    >> against the 10.5 SDK, so it would seem more reasonable to make the
    >> update to both the 32 and 64-bit runtimes, but only in the 10.5
    >> SDK. Then you could update the 10.5 SDK (to 10.5.1) to allow for
    >> this "syntactic sugar" under both 32- and 64-bit.
    >> I mean, after all, all it means is that you're changing the
    >> default size of an (Integer) register in the CPU chip, and
    >> updating the OS to take advantage. How would this make
    >> implementing (or not implementing) this change any harder or easier?
    >
    > The 32-bit runtime must remain binary compatible with all code that
    > was compiled and targeted for Tiger and earlier.
    >
    > It is extremely desirable to be able to link against the 10.5 SDK
    > and still deploy your application on Tiger (after taking
    > appropriate measures.)
      Huh? I thought the point of linking against a new SDK was to take
    advantage of features in that SDK, not to maintain backwards
    compatibility with the older OS features?

    >
    > By restricting this changes to the 64-bit runtime, all binary
    > compatibility issues are avoided, because there are no legacy 64-
    > bit applications.
    >
    > Jim
  • On Feb 17, 2008, at 9:47 AM, William Squires wrote:

    >> As it stands, you cannot add iVars to a base class in the 32-bit
    >> runtime without required that all subclasses be recompiled.
    > ??? Why should the subclasses know anything about the base class
    > other than what the base class exposes in its API (from the POV of
    > whomever is writing the subclass code, if they follow proper OO
    > methodologies)? Only if I rewrite the subclass to specifically use
    > the new iVar should I need to recompile it.

    <http://www.google.com/search?client=safari&rls=en-us&q=fragile+base
    +class&ie=UTF-8&oe=UTF-8
    >

    mmalc
  • On Feb 17, 2008, at 9:47 AM, William Squires wrote:
    > On Feb 17, 2008, at 11:13 AM, Jim Correia wrote:
    >> On Feb 17, 2008, at 11:59 AM, William Squires wrote:
    >>> But it doesn't answer the question. Why even make the change in
    >>> the 64-bit runtime? This would seem to hide a source of bugs, by
    >>> taking the responsibility for providing storage away from the
    >>> programmer. Some storage is still necessary.
    >> As it stands, you cannot add iVars to a base class in the 32-bit
    >> runtime without required that all subclasses be recompiled.
    > ??? Why should the subclasses know anything about the base class
    > other than what the base class exposes in its API (from the POV of
    > whomever is writing the subclass code, if they follow proper OO
    > methodologies)? Only if I rewrite the subclass to specifically use
    > the new iVar should I need to recompile it.
    > i.e. If I have a base class A

    It is an implementation detail.

    In the legacy -- 32 bit -- runtime, each subclass effectively tacks
    its instance variables onto the end of the superclass's instance
    variables as if it were all one big extensible C structure.  If the
    superclass adds an ivar, the offset of the ivars in said structure are
    thus incorrect and, unless you recompile, subclasses will read/write
    from the wrong spot in memory and *boom*.

    The modern -- 64 bit -- runtime fixes this particular issue.

    >
    >> This is particularly important for frameworks like AppKit. An
    >> AppKit class cannot have an iVar added to it because it would break
    >> binary compatibility with everyone who subclassed it. The 64-bit
    >> runtime solves this problem.
    >>
    > How? And, more importantly, why? What advantage is added by hiding
    > the need for the storage? And what happens if you follow the older
    > model and still provide the storage anyway?

    In the modern runtime, it doesn't matter if you have properties
    synthesize the storage or you declare the storage explicitly, you can
    still modify the superclass's inventory of instance variables --
    explicitly or through synthesis -- without requiring subclasses to be
    recompiled.

    There is a very good reason for "hiding the storage" -- for
    synthesizing the storage of an instance variable. By doing so, you
    force all access to said instance variable to go through either the
    synthesized setter/getter or your own implementation of the setter/
    getter.  Without jumping through some significant hoops, some random
    bit of code external to your class isn't going to be able to diddle
    the instance variables of your class directly.

    >>> And besides, in order to take advantage of Leopard features like
    >>> this one (whether on PPC or Intel), you should still have to link
    >>> against the 10.5 SDK, so it would seem more reasonable to make the
    >>> update to both the 32 and 64-bit runtimes, but only in the 10.5
    >>> SDK. Then you could update the 10.5 SDK (to 10.5.1) to allow for
    >>> this "syntactic sugar" under both 32- and 64-bit.
    >>> I mean, after all, all it means is that you're changing the
    >>> default size of an (Integer) register in the CPU chip, and
    >>> updating the OS to take advantage. How would this make
    >>> implementing (or not implementing) this change any harder or easier?
    >>
    >> The 32-bit runtime must remain binary compatible with all code that
    >> was compiled and targeted for Tiger and earlier.
    >>
    >> It is extremely desirable to be able to link against the 10.5 SDK
    >> and still deploy your application on Tiger (after taking
    >> appropriate measures.)
    > Huh? I thought the point of linking against a new SDK was to take
    > advantage of features in that SDK, not to maintain backwards
    > compatibility with the older OS features?

    Linking against a new SDK provides for the ability to take advantage
    of the new API provided by said SDK.

    But this isn't an API issue, this is an ABI issue.  The features of
    the modern runtime *** REQUIRE *** a different ABI that is
    incompatible with prior releases of Mac OS X.

    Thus, the decision was made to only offer the modern runtime features
    for 64 bit applications on Leopard and beyond.  There was no binary
    compatibility issues as there was no prior release of Mac OS X that
    offered 64 bit Objective-C support.

    b.bum
  • On Feb 17, 2008, at 12:47 PM, William Squires wrote:

    >> The 32-bit runtime must remain binary compatible with all code that
    >> was compiled and targeted for Tiger and earlier.
    >>
    >> It is extremely desirable to be able to link against the 10.5 SDK
    >> and still deploy your application on Tiger (after taking
    >> appropriate measures.)
    >
    > Huh? I thought the point of linking against a new SDK was to take
    > advantage of features in that SDK, not to maintain backwards
    > compatibility with the older OS features?

    Suppose there is a new framework feature on Leopard that I want to
    take advantage of. I link against the 10.5 SDK and in my code d

    if (some feature available) {
    ...
    } else {
    ... some alternate code, or nothing at all ...
    }

    The resulting binary can, with care, still work on 10.4 and earlier.

    Jim
  • On Feb 17, 2008, at 12:03 PM, Bill Bumgarner wrote:

    > On Feb 17, 2008, at 9:47 AM, William Squires wrote:
    >> On Feb 17, 2008, at 11:13 AM, Jim Correia wrote:
    >>> On Feb 17, 2008, at 11:59 AM, William Squires wrote:
    >>>> But it doesn't answer the question. Why even make the change in
    >>>> the 64-bit runtime? This would seem to hide a source of bugs, by
    >>>> taking the responsibility for providing storage away from the
    >>>> programmer. Some storage is still necessary.
    >>> As it stands, you cannot add iVars to a base class in the 32-bit
    >>> runtime without required that all subclasses be recompiled.
    >> ??? Why should the subclasses know anything about the base class
    >> other than what the base class exposes in its API (from the POV of
    >> whomever is writing the subclass code, if they follow proper OO
    >> methodologies)? Only if I rewrite the subclass to specifically use
    >> the new iVar should I need to recompile it.
    >> i.e. If I have a base class A
    >
    > It is an implementation detail.
    >
    > In the legacy -- 32 bit -- runtime, each subclass effectively tacks
    > its instance variables onto the end of the superclass's instance
    > variables as if it were all one big extensible C structure.  If the
    > superclass adds an ivar, the offset of the ivars in said structure
    > are thus incorrect and, unless you recompile, subclasses will read/
    > write from the wrong spot in memory and *boom*.
    >
    > The modern -- 64 bit -- runtime fixes this particular issue.
    >
    Okay, that explains it - weird... I wonder why ObjC did that?

    >>
    >>> This is particularly important for frameworks like AppKit. An
    >>> AppKit class cannot have an iVar added to it because it would
    >>> break binary compatibility with everyone who subclassed it. The
    >>> 64-bit runtime solves this problem.
    >>>
    >> How? And, more importantly, why? What advantage is added by hiding
    >> the need for the storage? And what happens if you follow the older
    >> model and still provide the storage anyway?
    >
    > In the modern runtime, it doesn't matter if you have properties
    > synthesize the storage or you declare the storage explicitly, you
    > can still modify the superclass's inventory of instance variables
    > -- explicitly or through synthesis -- without requiring subclasses
    > to be recompiled.
    >
    > There is a very good reason for "hiding the storage" -- for
    > synthesizing the storage of an instance variable. By doing so, you
    > force all access to said instance variable to go through either the
    > synthesized setter/getter or your own implementation of the setter/
    > getter.  Without jumping through some significant hoops, some
    > random bit of code external to your class isn't going to be able to
    > diddle the instance variables of your class directly.
    >
    >>>> And besides, in order to take advantage of Leopard features like
    >>>> this one (whether on PPC or Intel), you should still have to
    >>>> link against the 10.5 SDK, so it would seem more reasonable to
    >>>> make the update to both the 32 and 64-bit runtimes, but only in
    >>>> the 10.5 SDK. Then you could update the 10.5 SDK (to 10.5.1) to
    >>>> allow for this "syntactic sugar" under both 32- and 64-bit.
    >>>> I mean, after all, all it means is that you're changing the
    >>>> default size of an (Integer) register in the CPU chip, and
    >>>> updating the OS to take advantage. How would this make
    >>>> implementing (or not implementing) this change any harder or
    >>>> easier?
    >>>
    >>> The 32-bit runtime must remain binary compatible with all code
    >>> that was compiled and targeted for Tiger and earlier.
    >>>
    >>> It is extremely desirable to be able to link against the 10.5 SDK
    >>> and still deploy your application on Tiger (after taking
    >>> appropriate measures.)
    >> Huh? I thought the point of linking against a new SDK was to take
    >> advantage of features in that SDK, not to maintain backwards
    >> compatibility with the older OS features?
    >
    > Linking against a new SDK provides for the ability to take
    > advantage of the new API provided by said SDK.
    >
    > But this isn't an API issue, this is an ABI issue.  The features of
    > the modern runtime *** REQUIRE *** a different ABI that is
    > incompatible with prior releases of Mac OS X.
    >
    > Thus, the decision was made to only offer the modern runtime
    > features for 64 bit applications on Leopard and beyond.  There was
    > no binary compatibility issues as there was no prior release of Mac
    > OS X that offered 64 bit Objective-C support.
    >
    > b.bum
  • Le 17 févr. 08 à 19:52, William Squires a écrit :

    >
    > On Feb 17, 2008, at 12:03 PM, Bill Bumgarner wrote:
    >
    >> On Feb 17, 2008, at 9:47 AM, William Squires wrote:
    >>> On Feb 17, 2008, at 11:13 AM, Jim Correia wrote:
    >>>> On Feb 17, 2008, at 11:59 AM, William Squires wrote:
    >>>>> But it doesn't answer the question. Why even make the change in
    >>>>> the 64-bit runtime? This would seem to hide a source of bugs, by
    >>>>> taking the responsibility for providing storage away from the
    >>>>> programmer. Some storage is still necessary.
    >>>> As it stands, you cannot add iVars to a base class in the 32-bit
    >>>> runtime without required that all subclasses be recompiled.
    >>> ??? Why should the subclasses know anything about the base class
    >>> other than what the base class exposes in its API (from the POV of
    >>> whomever is writing the subclass code, if they follow proper OO
    >>> methodologies)? Only if I rewrite the subclass to specifically use
    >>> the new iVar should I need to recompile it.
    >>> i.e. If I have a base class A
    >>
    >> It is an implementation detail.
    >>
    >> In the legacy -- 32 bit -- runtime, each subclass effectively tacks
    >> its instance variables onto the end of the superclass's instance
    >> variables as if it were all one big extensible C structure.  If the
    >> superclass adds an ivar, the offset of the ivars in said structure
    >> are thus incorrect and, unless you recompile, subclasses will read/
    >> write from the wrong spot in memory and *boom*.
    >>
    >> The modern -- 64 bit -- runtime fixes this particular issue.
    >>
    > Okay, that explains it - weird... I wonder why ObjC did that?

    That's not an obj-c issue. That's a runtime and compiler issue. If you
    want to know why the OS X runtime did that, you will have to go back
    to the NeXT's days.
  • On Feb 17, 2008 1:03 PM, Bill Bumgarner <bbum...> wrote:

    In the legacy -- 32 bit -- runtime, each subclass effectively tacks
    > its instance variables onto the end of the superclass's instance
    > variables as if it were all one big extensible C structure.  If the

    Okay, I can see how the basic assumption of one big continuous block of
    memory might be limiting.

    But, having said that... :-)

    > superclass adds an ivar, the offset of the ivars in said structure are
    > thus incorrect and, unless you recompile, subclasses will read/write
    > from the wrong spot in memory and *boom*.

    Why would the parent's size be hard-coded? You can get the size of the
    parent at run time, by dereferencing a couple of levels into isa. All the
    compiler would have to do is emit code that walks down isa to get the
    parent's size, and add it to self to establish a base address. The only
    hard-coded offsets would then be relative to that base, for the current
    class' own ivars.

    Changing the size of the parent class wouldn't break such a scheme, so far
    as ordinary usage goes. People playing games with sizeof() or @defs deserve
    whatever breakage they get. :-)

    Doesn't the current (I refuse to call it "legacy" quite yet...) 32-bit
    compiler emit code like that when ivars are accessed?

    sherm--
  • On Feb 17, 2008, at 10:52 AM, William Squires wrote:
    > Okay, that explains it - weird... I wonder why ObjC did that?

    When Objective-C was created, the targeted machines had relatively
    little memory -- 4MB or less, typically.

    As such, every single byte that could be saved was valuable.  So, as
    a simple extension of C, Objective-C classes are really just a
    glorified C structure that is extended across subclasses and has a
    slot at the head that can point to the class of the structure.

    Simple.  Elegant.  Compact.  Easy to implement.  And prone to the
    fragile base class problem.

    While memory is still at a premium, eating a couple of pointers worth
    of memory to solve the fragile base class problem is now a worthwhile
    tradeoff.

    It would have been nice if this change could have been made in the
    10.0 timeframe when there wasn't a binary compatibility issue
    preventing adoption in 32 bits.  But, at the time, there were other
    priorities that out weighed solving this particular problem.

    b.bum
  • On Feb 17, 2008, at 12:03 PM, Sherm Pendley wrote:
    > Why would the parent's size be hard-coded? You can get the size of
    > the parent at run time, by dereferencing a couple of levels into
    > isa. All the compiler would have to do is emit code that walks down
    > isa to get the parent's size, and add it to self to establish a base
    > address. The only hard-coded offsets would then be relative to that
    > base, for the current class' own ivars.
    >
    > Changing the size of the parent class wouldn't break such a scheme,
    > so far as ordinary usage goes. People playing games with sizeof() or
    > @defs deserve whatever breakage they get. :-)
    >
    > Doesn't the current (I refuse to call it "legacy" quite yet...) 32-
    > bit compiler emit code like that when ivars are accessed?

    To dive a little deeper, consider the instance variables for NSView,
    including  inherited ivars.  Well, a subset, really:

    @interface NSObject <NSObject> {
        Class    isa;
    }

    @interface NSResponder : NSObject <NSCoding>
    {
        id _nextResponder;
    }

    @interface NSView : NSResponder
    {
        NSRect              _frame;
        NSRect              _bounds;
        id                  _superview;
        id            _subviews;
        NSWindow            *_window;
    }

    Within the legacy runtime ;), the memory for NSView looks just like a
    C struct with this layout:

    struct NSViewLikeStruct {
        Class    isa;
        id _nextResponder;
        NSRect              _frame;
        NSRect              _bounds;
        id                  _superview;
        id            _subviews;
        NSWindow            *_window;
    };

    So, in the implementation of an NSView, an access to an instance
    variable -- say _subviews -- is compiled down to something equivalent
    to:

    ((struct NSViewLikeStruct *) aView)->_subviews

    Now, if an instance variable is added to NSObject or NSResponder and
    the subclasses are not compiled, the above code will have the wrong
    offset.

    This is fragile, but allows instances to be allocated as a single
    chunk of memory while also reducing the amount of metadata and/or
    indirection required to get at any given instance variable's slot.

    To fix the issue, it has to be done partially at runtime and requires
    a different layout for the instances...

    b.bum
  • On 17 Feb '08, at 12:03 PM, Sherm Pendley wrote:

    > Why would the parent's size be hard-coded? You can get the size of the
    > parent at run time, by dereferencing a couple of levels into isa.
    > All the
    > compiler would have to do is emit code that walks down isa to get the
    > parent's size, and add it to self to establish a base address. The
    > only
    > hard-coded offsets would then be relative to that base, for the
    > current
    > class' own ivars.

    This has been done before, most notably in IBM/Apple's "SOM" runtime
    that was used in OpenDoc in the mid-'90s. The main drawback is that it
    becomes more expensive to access instance variables. Instead of
    indexing off a constant offset from the object pointer, you have to
    call a runtime function that returns a pointer to the class's ivars,
    and index off that.

    It also adds some complexity to both the compiler and the runtime, to
    deal with the dynamic location of the ivars.

    The "Fragile Base Class" problem is common to many object runtimes. C+
    + has it even worse, in that the normal vtable-based runtime makes it
    impossible to add even *methods* to a base class without breaking
    subclasses. It turns out that fragile methods are much more of a
    problem than fragile instance variables; it's fairly easy to reserve a
    few unused ivars in advance and use them later on. So Obj-C has been
    able to work quite well in dynamic libraries, while C++ has usually
    fallen on its face. But it's nice that this last restriction is now
    lifted in the 64-bit environment.

    (Scripting languages don't generally suffer from this. Most of them
    store an object's ivars in a hashtable, which is much slower but much
    more flexible, so you can do crazy stuff like adding ivars to
    individual instances.)

    —Jens
previous month february 2008 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29    
Go to today
MindNode
MindNode offered a free license !