未释放 NSMutableRequest 对象主体的已分配数据



在我的应用程序中,我必须执行多部分POST请求。在请求中,我必须发送一个存储在设备照片库中的文件。在它完成上传并接收到返回的数据后,我向请求发送了一个释放消息,但Instruments显示数据仍然存在于设备的内存中。

我是这样创建请求对象的:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:YES];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];
NSString *boundary = @"---------------------------14737809831466499882746641449";
// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// post body
NSMutableData *body = [[NSMutableData alloc] init];
// add parts (all parts are strings) `parts` is a NSDictionary object
for(id key in parts) {
    [body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="%@"rnrn", key] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@rn", [parts objectForKey:key]] dataUsingEncoding:NSUTF8StringEncoding]];
}
// add files data - `file` is a ALAssetRepresentation object
NSData *fileData;
NSString *filename = [file filename];
Byte *buffer = (Byte*)malloc(file.size);
NSUInteger buffered = [file getBytes:buffer fromOffset:0.0 length:file.size error:nil];
fileData = [[NSData alloc] initWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];


if (fileData) {
    [body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    if ([requestType isEqualToString:PUBLISH_TYPE_VC_MANDA]) {
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="attachment"; filename="%@"rn", filename] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[@"Content-Type: image/jpegrnrn" dataUsingEncoding:NSUTF8StringEncoding]];
    } else {
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="file"; filename="%@"rn", filename] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[@"Content-Type: application/octet-streamrnrn" dataUsingEncoding:NSUTF8StringEncoding]];
    }
    [body appendData:fileData];
    [body appendData:[[NSString stringWithFormat:@"rn"] dataUsingEncoding:NSUTF8StringEncoding]];
}
[fileData release];

[body appendData:[[NSString stringWithFormat:@"--%@--rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

// setting the body of the post to the reqeust
[request setHTTPBody:body];
[body release];
// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"];
// set URL `adress` is a NSURL object
[request setURL:address];
//set cookie
if (storedCookie) {
    NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:[storedCookie name], NSHTTPCookieName, myDomain, NSHTTPCookieDomain,@"/",NSHTTPCookiePath, [storedCookie value], NSHTTPCookieValue, nil];
    NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:properties];
    NSArray* cookies = [NSArray arrayWithObjects: cookie, nil];
    NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
    [request setAllHTTPHeaderFields:headers];
}

在此之后,在我收到响应后,我执行[request release],但分配的字节保留在内存中。

我在分配模式下运行Instruments,它声称有一个类别Malloc 91MB的对象(我上传的ALAsset的大小)。通过查看调用树,占用所有内存的符号是上述方法中的[NSConcreteMutableData appendBytes:length:]

为什么不释放字节?更重要的是,为什么它必须将数据移动到设备的内存中?我看到像Facebook这样的应用程序从图库中上传非常大的视频而没有任何内存问题。

非常感谢您的关注,任何帮助或指导都将不胜感激

EDIT:进一步的调查显示,当我使用[request release]时,请求对象被释放,但它的主体不是。非常奇怪的行为…

EDIT2:我显式地使用了[request.HTTPBody release];,并且释放了字节。我仍然不能相信[request release]没有释放它的身体。

您的请求的retainCount为2:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; // 1

[request retain]; // 2

如果你做[request release],它会减少1。

解决方案是不做[request retain]

在进一步调查之后,内存没有被释放,因为请求的属性HTTPBody需要手动释放(参见我的第二个编辑)。

至于在NSRequest中发送大块数据,有一种更简单的方法,不会消耗设备的内存。您必须将文件写入磁盘,然后对其进行映射。我已经在这个SO回答中详细描述了它。希望对大家有所帮助

相关内容

  • 没有找到相关文章

最新更新