Using static NSString as observation context
-
I have recently changed some KVO observation code to us a static
NSString as the context when registering as KVO observation. However
now that seems to have introduced a crasher when removing the
observer, at least on a Core Duo Intel machine. PPC does not seem to
have any problem. So is there some problem using NSStrings as
observation context for Intel? The Sketch sample code also uses those.
Christiaan -
On 17/05/2008, at 11:59 PM, Christiaan Hofman wrote:> I have recently changed some KVO observation code to us a static
> NSString as the context when registering as KVO observation. However
> now that seems to have introduced a crasher when removing the
> observer, at least on a Core Duo Intel machine. PPC does not seem to
> have any problem. So is there some problem using NSStrings as
> observation context for Intel? The Sketch sample code also uses those.
I've not had a problem, but I cast the string to a void*. I use a
definition like this:
static void* MyObservationContext=(void*) @"MyObservationContext";
--
Rob Keniger -
On 18 May 2008, at 4:44 AM, Rob Keniger wrote:>
> On 17/05/2008, at 11:59 PM, Christiaan Hofman wrote:
>
>> I have recently changed some KVO observation code to us a static
>> NSString as the context when registering as KVO observation.
>> However now that seems to have introduced a crasher when removing
>> the observer, at least on a Core Duo Intel machine. PPC does not
>> seem to have any problem. So is there some problem using NSStrings
>> as observation context for Intel? The Sketch sample code also uses
>> those.
>
>
> I've not had a problem, but I cast the string to a void*. I use a
> definition like this:
>
> static void* MyObservationContext=(void*) @"MyObservationContext";
>
> --
> Rob Keniger
Thanks, I'll try it. Though I can't test it myself, as I don't see the
crash myself. It's a user reporting the problem (and the only change
in the relevant object's code has been the use of a context, that's
why I know it must be the cause).
Christiaan -
On Sun, May 18, 2008 at 12:23 PM, Christiaan Hofman <cmhofman...>
wrote:>But can this really make a difference? Aren't they both just the same size
> On 18 May 2008, at 4:44 AM, Rob Keniger wrote:
>
>
>> On 17/05/2008, at 11:59 PM, Christiaan Hofman wrote:
>>
>> I have recently changed some KVO observation code to us a static NSString
>>> as the context when registering as KVO observation. However now that seems
>>> to have introduced a crasher when removing the observer, at least on a Core
>>> Duo Intel machine. PPC does not seem to have any problem. So is there some
>>> problem using NSStrings as observation context for Intel? The Sketch sample
>>> code also uses those.
>>>
>>
>>
>> I've not had a problem, but I cast the string to a void*. I use a
>> definition like this:
>>
>> static void* MyObservationContext=(void*) @"MyObservationContext";
>>
>> --
>> Rob Keniger
>>
>
> Thanks, I'll try it. Though I can't test it myself, as I don't see the
> crash myself. It's a user reporting the problem (and the only change in the
> relevant object's code has been the use of a context, that's why I know it
> must be the cause).
>
> Christiaan
>
>
(that is, pointer size), for any architecture? And the pointer should never
be resolved anywhere (I definitely don't, I only compare using ==).
Christiaan -
On Sat, May 17, 2008 at 7:44 PM, Rob Keniger <rob...> wrote:>
> On 17/05/2008, at 11:59 PM, Christiaan Hofman wrote:
>
>> I have recently changed some KVO observation code to us a static NSString
>> as the context when registering as KVO observation. However now that seems
>> to have introduced a crasher when removing the observer, at least on a Core
>> Duo Intel machine. PPC does not seem to have any problem. So is there some
>> problem using NSStrings as observation context for Intel? The Sketch sample
>> code also uses those.
>
>
> I've not had a problem, but I cast the string to a void*. I use a definition
> like this:
>
> static void* MyObservationContext=(void*) @"MyObservationContext";
What is the point of doing this? Why are you trying to throw away type
information?
-Shawn -
On 18 May 2008, at 8:31 PM, Shawn Erickson wrote:> On Sat, May 17, 2008 at 6:59 AM, Christiaan Hofman
> <cmhofman...> wrote:
>> I have recently changed some KVO observation code to us a static
>> NSString as
>> the context when registering as KVO observation. However now that
>> seems to
>> have introduced a crasher when removing the observer, at least on a
>> Core Duo
>> Intel machine. PPC does not seem to have any problem. So is there
>> some
>> problem using NSStrings as observation context for Intel? The
>> Sketch sample
>> code also uses those.
>
> Can you be more specific about the crash you are seeing? (backtrace,
> etc.)
>
This is the top part of the crash
Thread 0 Crashed:
0 libobjc.A.dylib 0x90a59380 objc_msgSend + 16
1 com.apple.Foundation 0x928a26a7
-[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] +
233
2 com.apple.AppKit 0x93534a02 -[NSController
removeObserver:forKeyPath:] + 208
After that comes some app specific trace that clearly points to a
particular -removeObserver:forKeyPath: on NSUserDefaultsController in -
windowWillClose: for the main document window.> Are you removing the observation of the same key more then once? I
> have seen a over release bug in the Cocoa framework in situations like
> this (trying to locate my information on that issue...).
>
> -Shawn
No, -windowWillClose: can never be called twice, because the document
is closed after that. And the corresponding -addObserver:... is called
in -windowControllerDidLoadNib:, which is called for sure.
Christiaan -
On May 18, 2008, at 11:29 AM, Shawn Erickson wrote:>> static void* MyObservationContext=(void*) @"MyObservationContext";
>
> What is the point of doing this? Why are you trying to throw away type
> information?
Probably to supress compiler warnings?
- Scott -
On 19/05/2008, at 8:45 AM, Scott Stevenson wrote:>>> static void* MyObservationContext=(void*) @"MyObservationContext";
>>
>> What is the point of doing this? Why are you trying to throw away
>> type
>> information?
>
> Probably to supress compiler warnings?
Exactly. The method you use the context in has this signature so if
you don't cast to a void* you get a compiler warning:
- (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString
*)keyPathoptions:(NSKeyValueObservingOptions)options context:(void
*)context
--
Rob Keniger -
On Sun, May 18, 2008 at 6:15 PM, Rob Keniger <rob...> wrote:>
> On 19/05/2008, at 8:45 AM, Scott Stevenson wrote:
>
>>>> static void* MyObservationContext=(void*) @"MyObservationContext";
>>>
>>> What is the point of doing this? Why are you trying to throw away type
>>> information?
>>
>> Probably to supress compiler warnings?
>
> Exactly. The method you use the context in has this signature so if you
> don't cast to a void* you get a compiler warning:
You can assign any typed pointer to a void* without any warnings.
(unless you have some unusual warning enabled)
Anyway my question was more of what does this have to do with the
crash that the OP posted?
-Shawn -
On 19 May 2008, at 5:07 PM, Shawn Erickson wrote:> On Sun, May 18, 2008 at 6:15 PM, Rob Keniger <rob...>
> wrote:
>>
>> On 19/05/2008, at 8:45 AM, Scott Stevenson wrote:
>>
>>>>> static void* MyObservationContext=(void*) @"MyObservationContext";
>>>>
>>>> What is the point of doing this? Why are you trying to throw away
>>>> type
>>>> information?
>>>
>>> Probably to supress compiler warnings?
>>
>> Exactly. The method you use the context in has this signature so if
>> you
>> don't cast to a void* you get a compiler warning:
>
> You can assign any typed pointer to a void* without any warnings.
> (unless you have some unusual warning enabled)
>
> Anyway my question was more of what does this have to do with the
> crash that the OP posted?
>
> -Shawn
Indeed. The only way I think typing could have an effect of avoiding
such a crash is when there is a difference in size (or perhaps
endianess), so typing actually would do some real conversion. Hence my
question earlier. However I'm pretty sure that can never be relevant
for this case, as any pointer should have the same size (and nothing
it points to gets allocated or deallocated).
Christiaan -
On Sun, May 18, 2008 at 1:27 PM, Christiaan Hofman <cmhofman...> wrote:>
> On 18 May 2008, at 8:31 PM, Shawn Erickson wrote:
>
>> On Sat, May 17, 2008 at 6:59 AM, Christiaan Hofman <cmhofman...>
>> wrote:
>>>
>>> I have recently changed some KVO observation code to us a static NSString
>>> as
>>> the context when registering as KVO observation. However now that seems
>>> to
>>> have introduced a crasher when removing the observer, at least on a Core
>>> Duo
>>> Intel machine. PPC does not seem to have any problem. So is there some
>>> problem using NSStrings as observation context for Intel? The Sketch
>>> sample
>>> code also uses those.
>>
>> Can you be more specific about the crash you are seeing? (backtrace, etc.)
>>
>
> This is the top part of the crash
>
> Thread 0 Crashed:
> 0 libobjc.A.dylib 0x90a59380 objc_msgSend + 16
> 1 com.apple.Foundation 0x928a26a7
> -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] +
> 233
> 2 com.apple.AppKit 0x93534a02 -[NSController
> removeObserver:forKeyPath:] + 208
>
> After that comes some app specific trace that clearly points to a particular
> -removeObserver:forKeyPath: on NSUserDefaultsController in -windowWillClose:
> for the main document window.
That type of crash implies to me that the object you (indirectly) are
sending removeObserver:forKeyPath: to is no longer a valid object. Try
debugging with NSZombie enabled.
-Shawn -
On 19 May 2008, at 5:39 PM, Shawn Erickson wrote:> On Sun, May 18, 2008 at 1:27 PM, Christiaan Hofman
> <cmhofman...> wrote:
>>
>> On 18 May 2008, at 8:31 PM, Shawn Erickson wrote:
>>
>>> On Sat, May 17, 2008 at 6:59 AM, Christiaan Hofman <cmhofman...>
>>>>
>>> wrote:
>>>>
>>>> I have recently changed some KVO observation code to us a static
>>>> NSString
>>>> as
>>>> the context when registering as KVO observation. However now that
>>>> seems
>>>> to
>>>> have introduced a crasher when removing the observer, at least on
>>>> a Core
>>>> Duo
>>>> Intel machine. PPC does not seem to have any problem. So is there
>>>> some
>>>> problem using NSStrings as observation context for Intel? The
>>>> Sketch
>>>> sample
>>>> code also uses those.
>>>
>>> Can you be more specific about the crash you are seeing?
>>> (backtrace, etc.)
>>>
>>
>> This is the top part of the crash
>>
>> Thread 0 Crashed:
>> 0 libobjc.A.dylib 0x90a59380 objc_msgSend + 16
>> 1 com.apple.Foundation 0x928a26a7
>> -[NSObject(NSKeyValueObserverRegistration)
>> removeObserver:forKeyPath:] +
>> 233
>> 2 com.apple.AppKit 0x93534a02 -[NSController
>> removeObserver:forKeyPath:] + 208
>>
>> After that comes some app specific trace that clearly points to a
>> particular
>> -removeObserver:forKeyPath: on NSUserDefaultsController in -
>> windowWillClose:
>> for the main document window.
>
> That type of crash implies to me that the object you (indirectly) are
> sending removeObserver:forKeyPath: to is no longer a valid object. Try
> debugging with NSZombie enabled.
>
> -Shawn
That object is NSUserDefaultsController. That cannot be invalid
(unless there is a bug in AppKit).
Christiaan -
On 19 May 2008, at 17:48, Christiaan Hofman wrote:>
> On 19 May 2008, at 5:39 PM, Shawn Erickson wrote:
>>
>> That type of crash implies to me that the object you (indirectly) are
>> sending removeObserver:forKeyPath: to is no longer a valid object.
>> Try
>> debugging with NSZombie enabled.
>>
>> -Shawn
>
> That object is NSUserDefaultsController. That cannot be invalid
> (unless there is a bug in AppKit).
Not quite. Observers are implemented with some other hidden objects
and method redirection in the mix, so the remove message may not be
going direct to the NSUserDefaultsController. -
On 19 May 2008, at 7:56 PM, Paul Sargent wrote:>
> On 19 May 2008, at 17:48, Christiaan Hofman wrote:
>>
>> On 19 May 2008, at 5:39 PM, Shawn Erickson wrote:
>>>
>>> That type of crash implies to me that the object you (indirectly)
>>> are
>>> sending removeObserver:forKeyPath: to is no longer a valid object.
>>> Try
>>> debugging with NSZombie enabled.
>>>
>>> -Shawn
>>
>> That object is NSUserDefaultsController. That cannot be invalid
>> (unless there is a bug in AppKit).
>
> Not quite. Observers are implemented with some other hidden objects
> and method redirection in the mix, so the remove message may not be
> going direct to the NSUserDefaultsController.
Should not be relevant. I only send it
addObserver:forKeyPath:options:context: and removeObserver:forKeyPath:
messages. So even if they are forwarded to some other hidden objects,
they should never lead to over releasing. And the add/remove messages
are balanced, I can assure that.
Christiaan -
On 19 May 2008, at 7:56 PM, Paul Sargent wrote:>
> On 19 May 2008, at 17:48, Christiaan Hofman wrote:
>>
>> On 19 May 2008, at 5:39 PM, Shawn Erickson wrote:
>>>
>>> That type of crash implies to me that the object you (indirectly)
>>> are
>>> sending removeObserver:forKeyPath: to is no longer a valid object.
>>> Try
>>> debugging with NSZombie enabled.
>>>
>>> -Shawn
>>
>> That object is NSUserDefaultsController. That cannot be invalid
>> (unless there is a bug in AppKit).
>
> Not quite. Observers are implemented with some other hidden objects
> and method redirection in the mix, so the remove message may not be
> going direct to the NSUserDefaultsController.
The only other objects I can think of to be in play are the observer,
which should definitely be valid at this point, and the shared
NSUserDefaults object, which is the one ultimately being observed.
I am now pretty sure the static NSString must be a red haring. There
should be some other invalid object. As I'm pretty sure it's neither
the observer nor the controller, the only object I can think of is
NSUserDefaults.
One thing I've noticed: all crash reports are with 10.4 on a MacBook.
So I start to believe there is a Tiger AppKit bug involved. Has anyone
else seen problems with KVO on NSUserDefaultsController on Tiger?
Christiaan -
If you overrelease an object, including the user defaults controller,
it could be deallocated. Also, if an object is overreleased and gets
deallocated, that memory location can end up reused for some other
object.
Did you try running with zombies, as Shawn suggested? I would not
suspect a cocoa bug here.
-Ken
On Tue, May 27, 2008 at 5:56 AM, Christiaan Hofman <cmhofman...> wrote:>
> On 19 May 2008, at 7:56 PM, Paul Sargent wrote:
>
>>
>> On 19 May 2008, at 17:48, Christiaan Hofman wrote:
>>>
>>> On 19 May 2008, at 5:39 PM, Shawn Erickson wrote:
>>>>
>>>> That type of crash implies to me that the object you (indirectly) are
>>>> sending removeObserver:forKeyPath: to is no longer a valid object. Try
>>>> debugging with NSZombie enabled.
>>>>
>>>> -Shawn
>>>
>>> That object is NSUserDefaultsController. That cannot be invalid (unless
>>> there is a bug in AppKit).
>>
>> Not quite. Observers are implemented with some other hidden objects and
>> method redirection in the mix, so the remove message may not be going direct
>> to the NSUserDefaultsController.
>
> The only other objects I can think of to be in play are the observer, which
> should definitely be valid at this point, and the shared NSUserDefaults
> object, which is the one ultimately being observed.
>
> I am now pretty sure the static NSString must be a red haring. There should
> be some other invalid object. As I'm pretty sure it's neither the observer
> nor the controller, the only object I can think of is NSUserDefaults.
>
> One thing I've noticed: all crash reports are with 10.4 on a MacBook. So I
> start to believe there is a Tiger AppKit bug involved. Has anyone else seen
> problems with KVO on NSUserDefaultsController on Tiger?
>
> Christiaan
>
> _______________________________________________
> MacOSX-dev mailing list
> <MacOSX-dev...>
> http://www.omnigroup.com/mailman/listinfo/macosx-dev
> -
I know, but I never send an (auto)release message to NSUserDefaults or
NSUserDefaultsController, ever. Why would I, those are shared objects?
That's my point of saying that the object is the shared
NSUserDefaultsController, I thought that should be obvious. And it's
pretty easy to check that I don't, because I can easily find every
single occurrence where I send messages to those object in my code.
Unfortunately I cannot debug this problem, as I don't see the bug. I
only see the bug reports from my users. So running with zombies is
pointless.
Christiaan
On 27 May 2008, at 7:49 PM, Ken Ferry wrote:> If you overrelease an object, including the user defaults controller,
> it could be deallocated. Also, if an object is overreleased and gets
> deallocated, that memory location can end up reused for some other
> object.
>
> Did you try running with zombies, as Shawn suggested? I would not
> suspect a cocoa bug here.
>
> -Ken
>
> On Tue, May 27, 2008 at 5:56 AM, Christiaan Hofman
> <cmhofman...> wrote:
>>
>> On 19 May 2008, at 7:56 PM, Paul Sargent wrote:
>>
>>>
>>> On 19 May 2008, at 17:48, Christiaan Hofman wrote:
>>>>
>>>> On 19 May 2008, at 5:39 PM, Shawn Erickson wrote:
>>>>>
>>>>> That type of crash implies to me that the object you
>>>>> (indirectly) are
>>>>> sending removeObserver:forKeyPath: to is no longer a valid
>>>>> object. Try
>>>>> debugging with NSZombie enabled.
>>>>>
>>>>> -Shawn
>>>>
>>>> That object is NSUserDefaultsController. That cannot be invalid
>>>> (unless
>>>> there is a bug in AppKit).
>>>
>>> Not quite. Observers are implemented with some other hidden
>>> objects and
>>> method redirection in the mix, so the remove message may not be
>>> going direct
>>> to the NSUserDefaultsController.
>>
>> The only other objects I can think of to be in play are the
>> observer, which
>> should definitely be valid at this point, and the shared
>> NSUserDefaults
>> object, which is the one ultimately being observed.
>>
>> I am now pretty sure the static NSString must be a red haring.
>> There should
>> be some other invalid object. As I'm pretty sure it's neither the
>> observer
>> nor the controller, the only object I can think of is NSUserDefaults.
>>
>> One thing I've noticed: all crash reports are with 10.4 on a
>> MacBook. So I
>> start to believe there is a Tiger AppKit bug involved. Has anyone
>> else seen
>> problems with KVO on NSUserDefaultsController on Tiger?
>>
>> Christiaan
>>
>> _______________________________________________
>> MacOSX-dev mailing list
>> <MacOSX-dev...>
>> http://www.omnigroup.com/mailman/listinfo/macosx-dev
>> -
On 27 May 2008, at 1:16 PM, Christiaan Hofman wrote:> I know, but I never send an (auto)release message to NSUserDefaults
> or NSUserDefaultsController, ever. Why would I, those are shared
> objects? That's my point of saying that the object is the shared
> NSUserDefaultsController, I thought that should be obvious. And it's
> pretty easy to check that I don't, because I can easily find every
> single occurrence where I send messages to those object in my code.
I find that when I have a bug, I am often so convinced that I'm doing
everything perfectly, that I have to slap myself and say, "well, if
everything's perfect, you don't have a bug, do you?"
I find it pays to check whether things are going as well as I think
they are.> Unfortunately I cannot debug this problem, as I don't see the bug. I
> only see the bug reports from my users. So running with zombies is
> pointless.
No, it isn't. An overreleased object pointer will soon have another
object at the same address, making the pointer look valid to code that
thinks it is using the old object. It may be that for you, but not for
your users, the replacement object responds to enough of the old one's
methods that no crash or log messages (you've checked for those?)
occur. You are falsely "lucky."
But if you set NSZombieEnabled, you will catch those bugs, even on
your "lucky" machine. Just do the test.
â F -
On 27 May 2008, at 8:41 PM, Fritz Anderson wrote:> On 27 May 2008, at 1:16 PM, Christiaan Hofman wrote:
>
>> I know, but I never send an (auto)release message to NSUserDefaults
>> or NSUserDefaultsController, ever. Why would I, those are shared
>> objects? That's my point of saying that the object is the shared
>> NSUserDefaultsController, I thought that should be obvious. And
>> it's pretty easy to check that I don't, because I can easily find
>> every single occurrence where I send messages to those object in my
>> code.
>
> I find that when I have a bug, I am often so convinced that I'm
> doing everything perfectly, that I have to slap myself and say,
> "well, if everything's perfect, you don't have a bug, do you?"
>
> I find it pays to check whether things are going as well as I think
> they are.
>
Sure, but here the situation is really very clear and very much
contained. The only objects involved are my document and the
NSUserDefaults and associated classes. So I can easily check every
single instance of accessing the NSUserDefaults related objects (and I
did so several times now). And I do know the document object is valid
at this point, otherwise the stack trace would not be consistently
like this, it would show crashes just before this point, at least
sometimes.>> Unfortunately I cannot debug this problem, as I don't see the bug.
>> I only see the bug reports from my users. So running with zombies
>> is pointless.
>
> No, it isn't. An overreleased object pointer will soon have another
> object at the same address, making the pointer look valid to code
> that thinks it is using the old object. It may be that for you, but
> not for your users, the replacement object responds to enough of the
> old one's methods that no crash or log messages (you've checked for
> those?) occur. You are falsely "lucky."
Assuming that n fact it does occur. And I'm pretty much convinced that
it doesn't. I've never seen it, and in fact I've never seen a single
crash report form 10.5. All crash reports (from several users) occur
on 10.4.>
>
> But if you set NSZombieEnabled, you will catch those bugs, even on
> your "lucky" machine. Just do the test.
>
> â F
>
So I don't think it' about being lucky, it's just not happening for
me. BTW, I tried NSZombieEnabled, and nothing showed up.
Christiaan


