2013-05-01 87 views
6

我使用NSInputstream & NSOutputstream來設置連接併發送數據。我的流對象具有打開和關閉流的功能。我使用下面的代碼:CFStreamCreatePairWithSocketToHost中的內存泄漏iOS

@interface Stream() 
{ 
    NSInputStream *inputStream; 
    NSOutputStream *outputStream; 
} 

-(id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     inputStream = nil; 
     outputStream = nil; 
    } 
    return self; 
} 

-(int)streamOpenWithIp:(NSString *)ip withPortNumber:(int)portNumber; 
{ 
     CFReadStreamRef readStream; 
     CFWriteStreamRef writeStream; 

     CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)ip, portNumber, &readStream, &writeStream); 

     if(readStream && writeStream) 
     { 
      //Setup inpustream 
      inputStream = (__bridge NSInputStream *)readStream; 
      [inputStream setDelegate:self]; 
      [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
      [inputStream open]; 

      //Setup outputstream 
      outputStream = (__bridge NSOutputStream *)writeStream; 
      [outputStream setDelegate:self]; 
      [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
      [outputStream open]; 
     } 
} 

- (int)streamClose; 
{ 
     CFReadStreamSetProperty((__bridge CFReadStreamRef)(inputStream), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 
     CFReadStreamSetProperty((__bridge CFReadStreamRef)(outputStream), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 

     //Close and reset inputstream 
     [inputStream setDelegate:nil]; 
     [inputStream close]; 
     [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
     inputStream = nil; 

     //Close and reset outputstream 
     [outputStream setDelegate:nil]; 
     [outputStream close]; 
     [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
     outputStream = nil; 
} 

當我多次打開和關閉流時,此代碼正常工作。當我用儀器檢查我的應用程序內存泄漏時,它表示功能CFStreamCreatePairWithSocketToHost將內存泄漏了72%。有人知道我在做什麼錯嗎?我無法弄清楚。

回答

11

streamClose方法中加上CFRelease((CFStreamRef)inputStream);CFRelease((CFStreamRef)outputStream);

CFStreamCreatePairWithSocketToHost回報的readStreamwriteStream所有權被傳遞到你:

Ownership follows the Create Rule in Memory Management Programming Guide for Core Foundation. 

核心基礎對象需要使用ARC時甚至明確釋放:

The compiler does not automatically manage the lifetimes of Core Foundation objects; you 
must call CFRetain and CFRelease (or the corresponding type-specific variants) as dictated 
by the Core Foundation memory management rules (see Memory Management Programming Guide 
for Core Foundation). 

另外,更改此行(和相應的行outputStream):

inputStream = (__bridge NSInputStream *)readStream; 

到:

inputStream = (__bridge_transfer NSInputStream *)readStream; 

這是因爲readStream擁有一支優秀的保留計數這ARC是不知道的。通過給ARC這個指針的所有權,你可以在適當的時候授予它釋放指針的權限。深入閱讀:1,2

+0

我在我的項目中使用自動引用計數,所以我不能使用發佈。它是否爲我自動完成? – 2013-05-02 07:05:43

+0

檢查我的更新 – Mar0ux 2013-05-02 07:14:33

+0

它的工作!沒有內存泄漏了。我認爲你的意思是NSInputStream而不是NSString在你的答案? – 2013-05-02 09:25:57