ios - CFStreamCreatePairWithSocketToHost iOS 中的内存泄漏

标签 ios objective-c memory memory-leaks nsstream

我使用 NSInputstreamNSOutputstream 来建立连接并发送数据。我的流对象具有打开和关闭流的功能。我使用以下代码:

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

当我多次打开和关闭流时,此代码工作正常。当我使用 Instruments 检查我的应用程序是否存在内存泄漏时,它说函数 CFStreamCreatePairWithSocketToHost 正在泄漏 72% 的内存。有人知道我做错了什么吗?我想不通。

最佳答案

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

CFStreamCreatePairWithSocketToHost 返回时,readStreamwriteStream 的所有权将传递给您:

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

即使使用 ARC,Core Foundation 对象也需要显式释放:

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

关于ios - CFStreamCreatePairWithSocketToHost iOS 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16320548/

相关文章:

ios - Xcode IBOutlet 链接错误

iphone - 关闭 modalviewcontroller 后调用 viewwillappear

java - 内存不足错误 - 可能是由于内存泄漏?

MongoDB MongoError : Out of memory

ios - JSONKit 基准测试

ios - 从 sqlite3_prepare_v2 失败。错误是 : out of memory

iphone - 在将应用程序提交到 App Store 之前忘记删除断点

c - 通过将 void 指针转换为不同的结构指针来访问其内容

iOS 7 获取所有可用的音频设备(蓝牙、耳机、扬声器、电话)

ios - 带有单独数据源对象的 UITableViewController