(NSError **) error ; Why two pointers (*)?

Discussion in 'Mac Programming' started by Extreme343GS, Apr 30, 2010.

  1. Extreme343GS, Apr 30, 2010
    Last edited by a moderator: Nov 8, 2011

    Extreme343GS macrumors newbie

    Joined:
    Jan 26, 2010
    #1
    Code:
    - (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error
    Just why does NSError have two pointers? What does it actually mean?
     
  2. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #2
    It's a pointer to a pointer.

    Since all Objective-C objects *must* be referenced through pointers you can really think of "NSError*" as "an NSError". So an "NSError**" is "a pointer to an NSError".

    In this case, you're supposed to do something like this:
    Code:
    NSError *errorToBeFilledIn = nil;
    [@"foo" writeToFile:aFile atomically:YES encoding:NSUTF8StringEncoding error:&errorToBeFilledIn];
    if (errorToBeFilledIn != nil) {
        //handle the error
    }
    
     
  3. gnasher729, Apr 30, 2010
    Last edited by a moderator: Nov 8, 2011

    gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #3
    Get out your old C book and look up what a pointer is.

    Now write a void function that is supposed to return the age of some person in years as an int, and the weight in pounds as an int. How do you write this function, and how do you call it?

    And now write a function that is supposed to return a BOOL as its return value, and that also can optionally return an NSError*. How do you write this function, and how do you call it?
     
  4. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    This is basically covered in the replies above, but in my mind the rationale for this is that NSError is immutable. You couldn't pass in an instantiated NSError and get anything of value back, because the object could not be changed. Therefore, you need to get a new NSError object. If you just pass the pointer to an NSError by value, then the only way for something good to happen would be for the method to somehow get a brand new NSError at the exact same memory location that you passed in. This isn't really possible, so instead you pass a pointer to your NSError * so a new NSError can be alloc'd/init'd and the pointer to the new Object can be assigned to your NSError **.

    The ** is pretty rare, often because the "result" of a call is it's return value.

    -Lee
     
  5. goatless, Apr 30, 2010
    Last edited by a moderator: Nov 8, 2011

    goatless macrumors member

    goatless

    Joined:
    Oct 19, 2009
    #5
    I'm not familiar with your code, but here is sample code where a double-pointer is used:

    Code:
    #include <stdio.h>
    
    void get( char ** msg )
    {
    	*msg = strdup( "This string will survive beyond this function." );
    }
    
    void get_bad( char * msg )
    {
    	// The memory in msg will be lost after exiting this function.
    	msg = strdup( "Not seen outside this function" );
    }
    
    int main()
    {
    	char *msg = NULL;
    
    	get( &msg );
    
    	if( msg )
    	{
    		printf( "Got this message: '%s'\n", msg );
    		free( msg );
    		msg = NULL;
    	}
    	else
    	{
    		printf( "We'll get here if the memory allocation in 'get' failed.\n" );
    	}
    
    
     	get_bad( msg );
    
    	if( msg )
    	{
    		printf( "We'll never get here, but, anyway: '%s'\n", msg );
    		free( msg );
    	}
    	else
    	{
    		printf( "Didn't get a message, as expected.\n" );
    	}	
    
    	return 0;
    }
    The 'get' function allocates memory for the parameter passed to it, just as the function taking the NSError instance can allocate memory for it.

    As Catfish_Man has written in his sample, memory is allocated for NSError only when there is an error. That allows you to detect an error and get details in one object. It sounds reasonable.
     
  6. Extreme343GS thread starter macrumors newbie

    Joined:
    Jan 26, 2010
    #6
    Damn 2 many sad smilies.
    Anyway thanks esp @goatless.
     
  7. KirstenD macrumors newbie

    Joined:
    Aug 15, 2011
    #7
    +1 for the code :) It always helps when dealing with pointers and dynamically allocated memory.
     

Share This Page