ARC and varargs calls BAD_ACCESS

I look at the varargs list, and when I get to the last object in the list, I always get the BAD_ACCESS error. I strongly believe this is an ARC problem.

This is what I do:

 -(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; } 

I need to somehow tell the compiler to save the result returned by va_arg , but I cannot figure out where and how to apply this paradigm.

Update 1: This is how I call my method:

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

Update 2:. I updated my question and added the error I made to show what I actually did wrong. See my answer below.

+4
source share
6 answers

Whenever you have a list of varargs in C, you need to somehow indicate the number of elements in the list or determine the last element - the language does not do this for you. It can be through a format operator - the number of arguments corresponds to the number of format elements - or some other scheme. The default scheme is to end the parameter list in the calling statement with nil or NULL .

If you look at the definitions of things like NSArray arrayWithObjects , the list should always end with nil .

+1
source

I was on the wrong track. The problem was not the function at all, but the way I called the function (other participants could not know this because I did not make a mistake in my example in my question).

I updated my question and the actual problem was that I did not pass a list of NSStrings, but 5 NSStrings and last were a normal C-string C.

The last line of C called BAD_ACCESS :

BADLY:

 "Smith" 

WELL:

 @"Smith" 

Now I'm confused :-)

+3
source

I also work with ARC , I use the following template, and it works great for me, I never experienced any problems with it, this could help you:

 - (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); } 
+1
source

Today I faced the same problem and can tell you technically that this has nothing to do with ARC or save, but your method declaration / prototype should be

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

This way you pass the Xcode and C preprocessor to use MACRO and should always end with "nil", so it stops va_arg () from accessing the wrong position (BAD_ACCESS)

+1
source

This has nothing to do with ARC. va_arg does not verify that it is at the end of the list, so it will return a pointer to a block of memory after the list, which can be anything. Therefore, EXC_BAD_ACCESS. Usually you specify the number of arguments as an optional parameter, for example:

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

Then use numStrings in your while .

0
source

If you expect the id type from returning va_arg (in this example NSString *) and it returns nil, failure will occur. This is because the arc is trying to keep the return zero.

to avoid this, add __unsafe_unreded to the variable you are assigning.

0
source

All Articles