Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot understand NSError/NSObject pointer passing behavior

I am now confused by pointer to pointer even though I've read Why does NSError need double indirection? (pointer to a pointer) and NSError * vs NSError ** and much more.

I've done some thinking and still got some questions.

Here I wrote this:

NSError *error = [NSError errorWithDomain:@"before" code:0 userInfo:nil];
NSLog(@"outside error address: %p", &error];
[self doSomethingWithObj:nil error:&error];

In order to test the above NSError method, I wrote this:

- (id)doSomethingWithObj:(NSObject *)obj error:(NSError *__autoreleasing *)error
{
    NSLog(@"inside error address: %p", error);
    id object = obj;
    if (object != nil)
    {
        return object;
    }
    else
    {
        NSError *tmp = [NSError errorWithDomain:@"after" code:0 userInfo:nil];
        *error = tmp;
        return nil;
    }
}

But I found that the two logging addresses are different. Why is that?

2016-08-19 19:00:16.582 Test[4548:339654] outside error address: 0x7fff5b3e6a58
2016-08-19 19:00:16.583 Test[4548:339654] inside error address: 0x7fff5b3e6a50

Shouldn't they be the same since that was just a simple value copy? If they should be different, how can pointer to pointer end up pointing to the same NSError instance?

like image 916
Boris Avatar asked Aug 19 '16 11:08

Boris


1 Answers

The variable in the caller has type NSError*. The address has type NSError* *. The function expect NSError* __autoreleasing *. Therefore the compiler creates a hidden variable of type NSError* __autoreleasing, copies the NSError* into the hidden variable before the call, and copies it back after the call to get the semantics of __autoreleasing right.

like image 176
gnasher729 Avatar answered Oct 01 '22 17:10

gnasher729