2013-12-18 18 views
5

私は非アークプロジェクトでappleのReachabiliryクラスを使用します。また、メモリリークを検出するために計測器を使用して実行すると、Reachabilityメソッドが参照されます。ここに問題があります:Appleの到達可能性メモリリーク

+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress; 
{ 
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress); 

    WReachability* returnValue = NULL; 

    if (reachability != NULL) 
    { 
     returnValue = [[self alloc] init]; 
     if (returnValue != NULL) 
     { 
      returnValue->reachabilityRef = reachability; 
      returnValue->localWiFiRef = NO; 
     } 
    } 
    return returnValue; 
} 

リークされたオブジェクトは到達可能性とreturnValueです。 私はSCNetworkReachabilityCreateWithAddressが新しいインスタンスを作成することを理解しています。私はCFリリースする必要がありますが、deallocで正しく発生します。

- (void)dealloc 
{ 
    [self stopNotifier]; 
    if (reachabilityRef != NULL) 
    { 
     CFRelease(reachabilityRef); 
    } 
    [super dealloc]; 
} 

ここでメモリリークを回避するにはどうすればよいですか?

UPD: おそらく、到達可能性がどのように呼び出されるのでしょうか?私は、このメソッドを使用します。

[[Reachability reachabilityForInternetConnection] startNotifier]; 

そして、ちょうどこのラインを使用し、任意のオブジェクトに割り当てないでください:

+ (instancetype)reachabilityForInternetConnection; 
{ 
    struct sockaddr_in zeroAddress; 
    bzero(&zeroAddress, sizeof(zeroAddress)); 
    zeroAddress.sin_len = sizeof(zeroAddress); 
    zeroAddress.sin_family = AF_INET; 

    return [self reachabilityWithAddress:&zeroAddress]; 
} 

は、その後私はこのような到達可能性と呼ばれます。私はこれを変更しようとした は次のように呼び出します:

Reachability *reachability = [[Reachability reachabilityForInternetConnection] autorelease]; 
[reachability startNotifier]; 

しかし、このアナライザは、「あまりにも多くの自動リリース」私に言った後。

答えて

4

returnValueがNULLに等しい場合、到達可能性オブジェクトはリークされます。この場合、解放する必要があります。また、ココアは大会(https://developer.apple.com/library/ios/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-SW1)を命名することにより、あなたは自動解放オブジェクトを返す必要があります。

+ (instancetype)reachabilityWithAddress: 
{ 
    ... 
    returnValue = [[[self alloc] init] autorelease]; 

をしたり、新しいから例えば起動する方法の名前を変更する:あなたは自動解放オブジェクトを返すようにしたくない場合はnewReachabilityWithAddressまたはこのような何か。

Xcodeでスタティックアナライザーを実行しようとすると、問題を特定するのに役立ちます。

+0

とアナライザ&アークも命名規則に頼っています –

+0

Daij-Djan、説明できますか? – Maria

+0

また、私はちょうど質問を更新しました。 – Maria

0

コードの正しい修正は、deallocのCFReleaseに加えて次のとおりです。

以下のコードの本文をご覧ください。同様のボディは、reachabilityWithHostNameコードにも入る必要があります。

+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress 
{ 
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress); 

    Reachability* returnValue = NULL; 

    if (reachability != NULL) 
    { 
     returnValue = [[self alloc] init]; 
     if (returnValue != NULL) 
     { 
      returnValue->_reachabilityRef = CFRetain(reachability); 
      returnValue->_alwaysReturnLocalWiFiStatus = NO; 
     } 
     CFRelease(reachability); 
    } 
    return returnValue; 
} 
5

私はそれを次の方法で行う方が良いと思う:

+ (Reachability*) reachabilityWithHostName: (NSString*) hostName; 
{ 
    Reachability* retVal = NULL; 
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); 
    if(reachability!= NULL) 
    { 
     retVal= [[self alloc] init]; 
     if(retVal!= NULL) 
     { 
      retVal->reachabilityRef = reachability; 
      retVal->localWiFiRef = NO; 
     } 
     else 
     { 
      CFRelease(reachability); 
     } 
    } 
    return retVal; 
} 
8

@Alexartの答えは私のために働いていますが単純化されたバージョンをしたい場合は、

+(instancetype)reachabilityWithAddress:(void *)hostAddress 
{ 
    SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); 
    if (ref) 
    { 
     id reachability = [[self alloc] initWithReachabilityRef:CFBridgingRetain((__bridge id)ref)]; 
     CFRelease(ref); 
     return reachability; 
    } 
    return nil; 

}

1

を使用最新のreachability.mはARCが必要なようですが、私のアプリはそれを使用していません。

私はちょうどそれのためにそれをオンに:

  1. はそれにソース

  2. 検索の到達可能性と、ダブルクリックをコンパイル

  3. \ビルドフェーズ\ターゲットに行く

    -fobjcアークを追加

メモリリークが今行った

1

ARCを有効にしたソリューションReachabilityクラス。

  1. 問題の行の下にCFAutorelease(ref)を追加します。
  2. dealloc

    - (void)dealloc { 
        [self stopNotifier]; 
    
        self.reachableBlock   = nil; 
        self.unreachableBlock  = nil; 
        self.reachabilityBlock  = nil; 
        self.reachabilitySerialQueue = nil; 
    } 
    

    更新

    更新reachabilityWithAddress

    + (instancetype)reachabilityWithAddress:(void *)hostAddress { 
        SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); 
        if (ref) { 
         id reachability = [[self alloc] initWithReachabilityRef:ref]; 
         CFAutorelease(ref); 
         return reachability; 
        } 
    
        return nil; 
    } 
    

    更新dealloc

からCFRelease(self.reachabilityRef)コードを削除します

関連する問題