【问题标题】:Memory Leaks in CFStreamCreatePairWithSocketToHost iOSCFStreamCreatePairWithSocketToHost iOS 中的内存泄漏
【发布时间】:2013-04-25 14:13:23
【问题描述】:

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

@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% 的内存。有人知道我做错了什么吗?我想不通。

【问题讨论】:

    标签: ios objective-c memory memory-leaks nsstream


    【解决方案1】:

    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 该指针的所有权,您将授予它在适当时间释放指针的权限。延伸阅读:12

    【讨论】:

    • 我的项目中使用了自动引用计数,所以不能使用release。它会自动为我完成吗?
    • 成功了!不再有内存泄漏。我认为您的答案是 NSInputStream 而不是 NSString?
    • 是的,当然。感谢您指出。很高兴我能帮上忙!
    • 多么棒的答案!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多