Re: -performSelector: exception... in one build configuration
Re: -performSelector: exception... in one build configuration
- Subject: Re: -performSelector: exception... in one build configuration
- From: Steve Christensen <email@hidden>
- Date: Fri, 04 Nov 2011 08:03:31 -0700
On Nov 4, 2011, at 3:44 AM, Christiaan Hofman wrote:
> On Nov 4, 2011, at 7:13, Steve Christensen wrote:
>
>> To reiterate: This code has worked perfectly fine for nearly two years in all build configurations, both in the simulator and on the device. I have only run into this issue after upgrading to Xcode 4.2, and when building a release version for a device.
>>
>> The structure field is typed as SEL and the values are initialized using @selector(), not by stuffing a C string into it. Yes, there's obviously something wrong, but since all of the structs are initialized the same way and only one is failing (for one particular configuration), I'm trying to figure out what that might be.
>
> How you typed it is totally irrelevant, that is just a compiler directive. In fact, the *type* of a SEL is essentially the same as a char* (it's a typedef). But as I explained, the real difference is that a SEL is *registered* and unique. That is not because of its type, but about what it actually is at run time. And your test shows clearly that this one is NOT a selector, it's just some C-string. And again, WE cannot tell you why, because you did not give us information about HOW you created it.
I just used @selector, so I expect that the compiler will do the right thing and create the opaque structure that represents a selector.
> Moreover, your initialization story makes no sense. A @selector() is not a constant expression, so you cannot initialize a const variable using it.
You mean that
const SEL myConstantSelector = @selector(foo);
shouldn't work?
> So how DID you create the C-array of structs?
struct MyStruct
{
SEL selector;
...
};
static const MyStruct kArrayOfStructs[] =
{
{
@selector(foo),
...
},
{
@selector(bar),
...
},
...
};
...
- (void) crashingCode
{
...
[[NSUserDefaults standardUserDefaults] performSelector:kArrayOfStructs[i].selector];
...
}
>> On Nov 3, 2011, at 11:09 AM, Christiaan Hofman wrote:
>>
>>> From what you say it is obvious that your selector in the C-array of structs is wrong, one of the selectors is not really a SEL (i.e. a unique registered C-string) but rather just some C-string (that happens to have the same characters as the SEL). SELs should be unique, so they should always have the same address. They are NOT compared by comparing characters. So your bug is in the place where you build this C-array of structs. (And as you said exactly nothing about that, I cannot say what's wrong with it.)
>>>
>>> Christiaan
>>>
>>> On Nov 3, 2011, at 17:49, Steve Christensen wrote:
>>>
>>>> Yes, then -performSelector: executes without generating an exception. One interesting thing I noticed is that there's only a single instance of the literal string for the selector name in the link map, even though I'm seeing two different addresses for the selector for the same method. (And looking at the memory address for a SEL, it looks like it's currently just a null-terminated C string.)
>>>>
>>>>
>>>> On Nov 2, 2011, at 7:33 PM, Ludovic Nicolle wrote:
>>>>
>>>>> interesting.
>>>>>
>>>>> at least we know the selectors are not equal.
>>>>>
>>>>> if you replace storedSelector with supposedSelector, does it then performsSelector as expected ?
>>>>>
>>>>> Ludo
>>>>>
>>>>> On 2011-11-02, at 7:16 PM, Steve Christensen wrote:
>>>>>
>>>>>> On Nov 2, 2011, at 6:24 PM, Ludovic Nicolle wrote:
>>>>>>
>>>>>>> Hi Steve,
>>>>>>>
>>>>>>> well, as much as it is quite unlikely that the target object is invalid since you are using [NSUserDefaults standardUserDefaults], Michael's question can be slightly adapted to see if your selector is what you think.
>>>>>>>
>>>>>>>> I'm always messaging [NSUserDefaults standardUserDefaults]. I have a static array (not NSArray) of C structs, containing various bits of info, including a selector for a particular NSUserDefaults method in my category, so the code looks something like this:
>>>>>>>>
>>>>>>>> x = [[NSUserDefaults standardUserDefaults] performSelector:someItems[i].selector];
>>>>>>>
>>>>>>> if you write and execute this code:
>>>>>>>
>>>>>>> SEL storedSelector = someItems[i].selector;
>>>>>>> NSString* storedSelectorString = NSStringFromSelector(storedSelector);
>>>>>>>
>>>>>>> SEL supposedSelector = @selector(whateverYouThinkShouldBethere);
>>>>>>> NSString* supposedSelectorString = NSStringFromSelector(supposedSelector);
>>>>>>>
>>>>>>> BOOL selectorsEqual = (storedSelector == theSupposedSelector);
>>>>>>>
>>>>>>> if (selectorsEqual)
>>>>>>> NSLog(@"my two selectors are equal with a selector string = %@", storedSelectorString);
>>>>>>> else
>>>>>>> NSLog(@"my two selectors are different. \n storedSelector string = %@ \n supposedSelector string = %@ ", storedSelectorString, supposedSelectorString);
>>>>>>>
>>>>>>>
>>>>>>> whateverYouThinkShouldBethere should be the supposed selector, of course.
>>>>>>>
>>>>>>> What is the output?
>>>>>>
>>>>>>
>>>>>> I added one extra check that compares the two NSStringFromSelector() values as well. For the "good" configurations (simulator debug/release + device debug), I get:
>>>>>>
>>>>>> my two selectors are equal with a selector string = "foo"
>>>>>> my two selector names are equal with a selector string = "foo"
>>>>>>
>>>>>> For the "bad" configuration (device release), I get:
>>>>>>
>>>>>> my two selectors are different.
>>>>>> storedSelector string = "foo"
>>>>>> supposedSelector string = "foo"
>>>>>> my two selector names are equal with a selector string = "foo"
>>>>>>
>>>>>> steve
>>>>
>>>> _______________________________________________
>>>> Do not post admin requests to the list. They will be ignored.
>>>> Xcode-users mailing list (email@hidden)
>>>> Help/Unsubscribe/Update your Subscription:
>>>>
>>>> This email sent to email@hidden
>>>
>>
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden