29

I'm converting my socket client to ARC:

- (id)initWithHostname:(NSString *)hostname AndPort:(NSInteger)port
{
    if((self = [super init]))
    {
        oBuffer = [[NSMutableData alloc] init];
        iBuffer = [[NSMutableData alloc] init];

        iStream = [[NSInputStream alloc] init];
        oStream = [[NSOutputStream alloc] init];

        [NSStream getStreamsToHost:[NSHost hostWithName:hostname] port:port inputStream:&iStream outputStream:&oStream];

        ...
    }

    return self;
}

The error I got is:

error: Automatic Reference Counting Issue: Passing address of non-local object to __autoreleasing parameter for write-back

at this line on &iStream and &oStream:

[NSStream getStreamsToHost:[NSHost hostWithName:hostname] port:port inputStream:&iStream outputStream:&oStream];

Any help?

ricardopereira
  • 11,118
  • 5
  • 63
  • 81
kilianc
  • 7,397
  • 3
  • 26
  • 37

3 Answers3

41

This error is usually due to the non local variable address is passed to a method. Because the variable is declared as __strong by default, while the parameter of the method is __autoreleasing, so declare the parameter of the method invoked as __strong,like this: -(void)method:(id * __strong *)param.

Note that the method in the header file (.h file) must be declared as the same of the .m file.

ricardopereira
  • 11,118
  • 5
  • 63
  • 81
慭慭流觞
  • 436
  • 5
  • 3
  • 1
    This suggestion solved the issue completely. In my case the non ARC code, releases the passed ivar value and the other workaround of assigning the ivar to local temp variables, pass it to the target function and reassign it back to ivar as suggested by @Rudy Velthuis though solved the compiler error introduces EXC_BAD_ACCESS error in runtime as the released memory is still dangling and getting referenced inside the non ARC code after it has been released. – Rajaraman Subramanian Apr 30 '14 at 12:50
  • magically solved the problem, ty. – Boris Gafurov Aug 20 '22 at 00:18
15

Create two local variables, pass the addresses of them to the the method, then assign their values to the ivars after it returns.

Mann
  • 5,477
  • 6
  • 45
  • 57
12

I think you should not alloc and init the iStream and oStream variables. They are meant to receive. Without ARC this simply creates two memory leaks that go unnoticed. Now your compiler uses ARC and then it does matter. The receiving variables should be local:

So try:

    NSInputStream *iStream;
    NSOutputStream *oStream;

    oBuffer = [[NSMutableData alloc] init];
    iBuffer = [[NSMutableData alloc] init];

    [NSStream getStreamsToHost:[NSHost hostWithName:hostname] port:port inputStream:&iStream outputStream:&oStream];

That should work, AFAICT. But note: I can't test this here.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • Thank you Rudy, your code works. But i need some explanation. You are using two local pointers instead of my instance pointers for `iStream` and `oStream`, so i can't have an istance reference to my streams? This is because NSStream can change the stream at any time or what? – kilianc Aug 06 '11 at 08:19
  • @kilianc: I don't know. The error message complained about non-local variables, so I assumed they should be local. I don't have an ARC compiler to test it. You can then probably assign them to the properties or ivars. – Rudy Velthuis Aug 06 '11 at 10:11
  • There's a better answer here: http://stackoverflow.com/questions/7415301/automatic-reference-counting-issue-passing-address-of-non-local-object-to-aut – nduplessis Dec 09 '11 at 13:06
  • 3
    I'd say a much better answer is this one: http://stackoverflow.com/a/8829294/908621 – fishinear May 30 '12 at 12:01