Re: Crash when calling va_arg()
Re: Crash when calling va_arg()
- Subject: Re: Crash when calling va_arg()
- From: Nathan Day <email@hidden>
- Date: Thu, 05 Jul 2012 14:51:35 +1000
For function you can write a macro version of your function which calls, you function and appends a NULL to the VA_ARG macro. I don't normally do this but I have done something similar where I wanted macros to add meta data to a class, that expanded out into compete class method implementations.
On 05/07/2012, at 11:09 AM, email@hidden wrote:
> I prefer the NULL sentinel too. You might like to check if
> __attribute__((sentinel(0,1))) added to your function header gets the
> compiler to warn you if you forget it, very useful that.
>
>> Hi Fritz and Jens,
>>
>> It makes total sense now. Out of the two options (NULL sentinel vs a
>> number to indicate the number of args), I would choose NULL because out of
>> the two, it's more foolproof. Is there a consensus about which option is
>> considered best practice?
>>
>> Thanks again,
>>
>> -- Tito
>>
>> On Jul 4, 2012, at 4:43 PM, Fritz Anderson <email@hidden>
>> wrote:
>>
>>> On 4 Jul 2012, at 6:30 PM, Tito Ciuro wrote:
>>>
>>>> void blockStep(fooBlock firstBlock, ...)
>>>> {
>>>> va_list args;
>>>> va_start(args, firstBlock);
>>>> id result = nil;
>>>>
>>>> do {
>>>> result = firstBlock(result, nil);
>>>> NSLog(@"%@", result);
>>>> } while (nil != (firstBlock = va_arg(args, fooBlock)));
>>>>
>>>> va_end(args);
>>>> }
>>>>
>>>> The output looks like this:
>>>>
>>>>> 2012-07-04 16:18:40.000 BlockStep[12418:303] One!
>>>>> 2012-07-04 16:18:56.533 BlockStep[12418:303] One!, Two!
>>>>
>>>> I've eliminated the crash by adding a nil sentinel in blockStep():
>>>>
>>>> blockStep (
>>>> ^ (id result, NSError **error) {
>>>> NSMutableString *value = [NSMutableString new];
>>>> [value appendString:@"One!"];
>>>> return value;
>>>> },
>>>> ^ (id result, NSError **error) {
>>>> NSMutableString *value = [NSMutableString new];
>>>> if (nil != result) {
>>>> [value appendString:result];
>>>> [value appendString:@", "];
>>>> }
>>>> [value appendString:@"Two!"];
>>>> return value;
>>>> },
>>>> nil
>>>> );
>>>
>>>>
>>>> This allows it to work without crashing, but I'd like if possible to
>>>> avoid having to place the sentinel. Any ideas?
>>>
>>> Not possible.
>>>
>>> Notionally, all parameters are passed to C functions in memory on a
>>> stack, which is unformatted and could contain anything. A function has
>>> no way of knowing how many parameters have been pushed onto the stack,
>>> or where the memory trails off into saved processor state and the like,
>>> or the types, or the amounts of memory they subtendâ¦.
>>>
>>> Most variadic functions require sentinels (usually NULL) to tell them to
>>> stop looking for parameters. The best-known exceptions are
>>> printf()-family functions, which know what to find on the stack because
>>> the format string tells them.
>>>
>>> â F
>>>
>>> --
>>> Fritz Anderson
>>> Xcode 4 Unleashed: Don't bring your bathroom copy into the kitchen â
>>> were you raised in a barn?
>>> <http://x4u.manoverboard.org/>
>>>
>>>
>>>
>>
>>
>> _______________________________________________
>>
>> Cocoa-dev mailing list (email@hidden)
>>
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>
>> Help/Unsubscribe/Update your Subscription:
>>
>> This email sent to email@hidden
>
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden