4

我正在浏览一个可变参数列表,当我到达列表中的最后一个对象时,我总是会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:我更新了我的问题并添加了一个错误,以揭示我实际上做错了什么。请看下面我的回答。

4

6 回答 6

3

我完全走错了路。问题根本不是函数,而是我如何调用函数(其他参与者不可能知道这一点,因为我没有在我的问题的示例中犯错误)。

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

最后一个 C 字符串导致BAD_ACCESS

坏的:

"Smith"

好的:

@"Smith"

现在我很尴尬:-)

于 2012-07-20T07:39:42.673 回答
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);
}
于 2012-07-19T16:20:16.273 回答
1

每当您在 C 中有一个可变参数列表时,您都需要以某种方式指定列表中的项目数或标识最后一项——该语言不会为您做这件事。这可以通过格式声明——参数的数量与格式项的数量相匹配——或其他一些方案。默认方案是用nilor结束调用语句中的参数列表NULL

如果您查看诸如 之类的定义NSArray arrayWithObjects,则列表必须始终以 . 结尾nil

于 2012-07-19T12:29:25.623 回答
1

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

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

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

于 2014-01-02T22:00:20.717 回答
0

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

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

于 2013-10-30T23:26:13.817 回答
0

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

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

然后numStrings在你的while循环中使用。

于 2012-07-19T12:21:53.007 回答