Question

I understand that this may seems a very basic question, but I always thought that explaining (and understanding) basic question is the key to build clean and working code. I have the following fragment of code in a CoreData entity:

-(BOOL)validateForInsert:(NSError *__autoreleasing *)error {
    [super validateForInsert:error];
    return [self validateInternal:error];
}

-(BOOL)validateInternal:(NSError *__autoreleasing *)error {
  // checking attributes and build userInfo error
  if(anyErrors) {
    *error = [NSError errorWithDomain:appDomain code:200 userInfo:details];
    return NO;
  }
  return YES;
}

by running 'analyze' in Xcode I get the famous 'potential null dereference' when creating error. While the compiler is not giving any alert, and the code has always worked. This could be a question too, why the compiler doesn't warn me about that ?

But coming to the code, I perfectly know the solution, which is to check if (error != nil), but I am quite lost at this. The question start at the beginning, at the meaning of NSError *_autoreleasing* , why the surrounding star ? Which should be a pointer to a pointer ?

Supposing I would like to call the validateForInsert: by myself, how can I build an *_autoreleasing* object ?

The following question, I suppose is related to the question above: if I am building the *error from scratch, why am I suppose to check if nil first ?

Last but not least, the code works fine, the errors get intercepted, could you please spot a case that can have it fail or crash ? As I said I am using CoreData, a generic example would be fine, but another related to CoreData is appreciated.

thanks

Was it helpful?

Solution

*error = [NSError errorWithDomain:appDomain code:200 userInfo:details];

is syntactically correct, therefore the compiler does not warn. The Analyzer detects that this will crash at runtime if error = NULL, i.e. if you call

[myObj validateForInsert:NULL];

If you call

NSError *error;
[myObj validateForInsert:&error];

then you pass the address of error, therefore you pass a variable of type NSError * *.

The __autoreleasing modifier is a hint to the ARC compiler that the object assigned to error is an autoreleased object.

You can declare a variable to be autoreleasing with

NSError * __autoreleasing error;
[myObj validateForInsert:&error];

but normally you do not care. ARC just generates the correct code.

For details, read the Transitioning to ARC Release Notes. There are also lots of answers on this topic on stackoverflow.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top