ARC和varargs导致BAD_ACCESS

时间:2012-07-19 11:53:08

标签: iphone objective-c ios nsstring variadic-functions

我正在查看varargs列表,当我到达列表中的最后一个对象时,我总是遇到BAD_ACCESS错误。我强烈认为这是ARC相关问题。

这就是我的所作所为:

-(NSString *)replaceTokensWithStrings:(NSString *)firstKey, ... {

        va_list _arguments;
        va_start(_arguments, firstKey);

        for (NSString *_currentArgument = firstKey; _currentArgument != nil; _currentArgument = va_arg(_arguments, NSString*)) {
            NSLog(@"%@", _currentArgument);
        }

        va_end(_arguments);

    return nil;
}

我必须以某种方式告诉编译器保留va_arg返回的结果,但我似乎无法确定应用此范例的位置和方式。

更新1:这就是我调用方法的方法:

[@"Hello <firstname> <lastname>" replaceTokensWithStrings:
  @"firstname", @"Peter",
  @"lastname", "Smith", 
  nil];

更新2:我更新了我的问题,并添加了一个错误,我揭示了我实际上做错了什么。请参阅下面的答案。

6 个答案:

答案 0 :(得分:3)

我彻底走错了路。问题根本不是函数,而是我如何调用函数(其他参与者无法知道这一点,因为我在我的问题中没有在我的例子中做错误)。

我已经更新了我的问题,实际的问题是我没有传递NSStrings列表,但是没有传递5个NSStrings,最后一个是普通的C字符串。

最后一个C字符串导致BAD_ACCESS

<强> BAD:

"Smith"

不可

@"Smith"

现在我很尴尬: - )

答案 1 :(得分:1)

每当你在C中有一个varargs列表时,你需要以某种方式指定列表中的项目数或识别最后一项 - 语言不会为你做。这可以通过格式语句 - args的数量与格式项的数量匹配 - 或其他一些方案。默认方案是使用nilNULL结束调用语句中的参数列表。

如果查看NSArray arrayWithObjects等内容的定义,则必须始终使用nil终止列表。

答案 2 :(得分:1)

我正在使用ARC,我正在使用以下模式,它对我来说很好,我从来没有遇到任何问题,它可能对你有帮助:

- (void)workingWithDictionaries:(NSDictionary *)dictionary, ... {

    va_list _arguments;
    va_start(_arguments, dictionary);

    for (NSDictionary *_currentArgument = dictionary; _currentArgument != nil; _currentArgument = va_arg(_arguments, NSDictionary*)) {
        NSLog(@"%@", _currentArgument);
    }

    va_end(_arguments);
}

答案 3 :(得分:1)

我今天遇到了同样的问题,并且可以告诉你技术上它与ARC无关或保留,但你的方法声明/原型应该是

-(NSString *)replaceTokensWithStrings:(NSString *)firstKey, ... 
    NS_REQUIRES_NIL_TERMINATION;

这样你告诉Xcode和C预处理器使用MACRO并要求总是以'nil'结束,这样就会阻止va_arg()访问错误的位置(BAD_ACCESS)

答案 4 :(得分:0)

它与ARC无关。 va_arg不检查它是否到达列表的末尾,因此将返回指向列表后面的内存块的指针,这可以是任何内容。因此EXC_BAD_ACCESS。通常,您将参数的数量作为额外参数,例如:

-(void *)replaceTokensWithNumberOfStrings:(int)numStrings strings:(NSString *)str1, ... {

然后使用numStrings循环中的while

答案 5 :(得分:0)

如果您期望va_arg返回的id类型(在此示例中为NSString *)并返回nil值,则会发生崩溃。这是因为arc试图保留返回的nil。

要避免这种情况,请将__unsafe_unretained添加到您要分配的变量中。