Memory leaks in CFStreamCreatePairWithSocketToHost iOS

I use NSInputstream and NSOutputstream to configure the connection and send data. My stream object has a function to open and close a stream. I am using the following code:

 @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; } 

This code works great when I open and close a stream many times. When I check my application for memory leaks using tools, he said that the CFStreamCreatePairWithSocketToHost function passes memory by 72%. Does anyone know what I'm doing wrong? I can not understand.

+6
source share
1 answer

Add CFRelease((CFStreamRef)inputStream); and CFRelease((CFStreamRef)outputStream); to the streamClose method.

When CFStreamCreatePairWithSocketToHost returns, ownership of readStream and writeStream is transferred to you:

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

Core Foundation objects must be explicitly released even when using 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). 

Alternatively, change this line (and the corresponding line for outputStream ):

 inputStream = (__bridge NSInputStream *)readStream; 

to:

 inputStream = (__bridge_transfer NSInputStream *)readStream; 

This is because readStream has an outstanding save value that ARC does not know. By granting ARC ownership of this index, you give it permission to issue the index at the appropriate time. Further reading: 1 , 2

+11
source

Source: https://habr.com/ru/post/944055/


All Articles