我正在查看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:我更新了我的问题,并添加了一个错误,我揭示了我实际上做错了什么。请参阅下面的答案。
答案 0 :(得分:3)
我彻底走错了路。问题根本不是函数,而是我如何调用函数(其他参与者无法知道这一点,因为我在我的问题中没有在我的例子中做错误)。
我已经更新了我的问题,实际的问题是我没有传递NSStrings列表,但是没有传递5个NSStrings,最后一个是普通的C字符串。
最后一个C字符串导致BAD_ACCESS
:
<强> BAD:强>
"Smith"
不可强>
@"Smith"
现在我很尴尬: - )
答案 1 :(得分:1)
每当你在C中有一个varargs列表时,你需要以某种方式指定列表中的项目数或识别最后一项 - 语言不会为你做。这可以通过格式语句 - args的数量与格式项的数量匹配 - 或其他一些方案。默认方案是使用nil
或NULL
结束调用语句中的参数列表。
如果查看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添加到您要分配的变量中。