2013-05-01 74 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