Xcode static analyser complaining about potential

2019-08-15 04:13发布

I am using ARC with ios sdk 6.0.

I am pretty sure I have got some memory leaks which Im having trouble tracking down.

After running the static analyser, im getting warnings about the following two methods:

+ (id<MXURLRequest>) requestWithURL:(NSURL*)url {    
  MXASIURLRequest *request = [[MXASIURLRequest alloc] init];

  [request setUrl:url];

  return request; // STATIC ANALYSER: Potential leak of an object stored into 'request' 
}

- (id)parseBody:(NSError *)error {    
  NSString *contentType = [[_request responseHeaders] objectForKey:@"Content-Type"];

  id body = nil;

  if ([contentType hasPrefix:@"application/json"] ||
      [contentType hasPrefix:@"text/json"] ||
      [contentType hasPrefix:@"application/javascript"] ||
      [contentType hasPrefix:@"text/javascript"]) {        
    body = [NSJSONSerialization JSONObjectWithData:[_request responseData] options:NSJSONReadingMutableLeaves error:&error];
  } else if ([contentType hasPrefix:@"image/"] ||
           [contentType hasPrefix:@"audio/"] ||
           [contentType hasPrefix:@"application/octet-stream"]) {        
    body = [_request responseData];
  } else {
    body = [[NSString alloc] initWithData:[_request responseData] encoding:NSUTF8StringEncoding];
  }

  return body; // STATIC ANALYSER : Potential leak of an object stored into 'body'
}

The warnings are as follows...

Object leaked: object allocated and stored into 'request' is returned from a method
whose name ('requestWithURL:') does not start with 'copy', 'mutableCopy', 'alloc'
or 'new'.  This violates the naming convention rules given in the Memory Management 
Guide for Cocoa

Object leaked: object allocated and stored into 'body' is returned from a method
whose name ('parseBody:') does not start with 'copy', 'mutableCopy', 'alloc' or
'new'.  This violates the naming convention rules given in the Memory Management
Guide for Cocoa

Can anyone see what I've done wrong here? Are these warnings legitimate, or can they be ignored? To me these methods look valid for ARC to be able to handle automatic reference counting.

Any help would be much appreciated.

1条回答
Evening l夕情丶
2楼-- · 2019-08-15 04:23

ARC is clearly turned off either for the file that this is compiling down to, or on the whole project. The static analyzer only complains about this stuff when ARC is turned off, so I'll elaborate further with that in mind.

The Cocoa Memory Management Guidelines that the compiler references allow only a strict set of methods to return non-autoreleased objects from constructors under normal circumstances (those being 'init', 'copy', 'mutableCopy', and 'new'). Notice the pattern?

Because you are allocating an object in the convenience constructor, then handing it to the caller, you are the one that owns it, because you created it. What Cocoa wants you to do is append an autorelease to the end of that return so that it is now the caller's job to keep a reference to the newly constructed object:

+ (id<MXURLRequest>) requestWithURL:(NSURL*)url {
    MXASIURLRequest *request = [[MXASIURLRequest alloc] init]; +1, we own it

    [request setUrl:url];

    return [request autorelease]; // +0, it's the caller's problem now
}

As for the last method, Cocoa is complaining about you being inconsistent memory-wise. That method has the possibility of returning either an object with a +1, or +0 retain count because of your mixed use of constructors and conveniences. To illustrate:

- (id)parseBody:(NSError *)error {    
  NSString *contentType = [[_request responseHeaders] objectForKey:@"Content-Type"];

  id body = nil;

  if ([contentType hasPrefix:@"application/json"] ||
      [contentType hasPrefix:@"text/json"] ||
      [contentType hasPrefix:@"application/javascript"] ||
      [contentType hasPrefix:@"text/javascript"]) {        
    body = [NSJSONSerialization JSONObjectWithData:[_request responseData] options:NSJSONReadingMutableLeaves error:&error]; //returns +0
  } else if ([contentType hasPrefix:@"image/"] ||
           [contentType hasPrefix:@"audio/"] ||
           [contentType hasPrefix:@"application/octet-stream"]) {        
    body = [_request responseData]; //potentially returns +1
  } else {
    body = [[NSString alloc] initWithData:[_request responseData] encoding:NSUTF8StringEncoding]; //returns +1
  }

  return body; // STATIC ANALYSER : Potential leak of an object stored into 'body'
}

The analyzer is asking for consistency: Either use only constructors, or autorelease consistently.

查看更多
登录 后发表回答