Ios NSMutableRequest对象的分配数据';他的尸体没有被释放

Ios NSMutableRequest对象的分配数据';他的尸体没有被释放,ios,objective-c,xcode,memory-management,xcode-instruments,Ios,Objective C,Xcode,Memory Management,Xcode Instruments,在我的应用程序中,我必须执行多部分POST请求。在请求中,我必须发送一个存储在设备照片库中的文件。在完成上传并收到返回的数据后,我向请求发送一条释放消息,但Instruments向我显示数据仍保留在设备内存中 以下是创建请求对象的方式: NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData

在我的应用程序中,我必须执行多部分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:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", [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:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

    if ([requestType isEqualToString:PUBLISH_TYPE_VC_MANDA]) {
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"attachment\"; filename=\"%@\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    } else {
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    }
    [body appendData:fileData];
    [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}

[fileData release];


[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", 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];
}
在此之后,在收到响应后,我执行
[请求释放]
,但分配的字节保留在内存中

我在分配模式下运行了
Instruments
,它声称有一个类别为
malloc91mb
(我正在上传的集合大小)的对象。通过查看调用树,占用所有内存的符号是上述方法中的
[nsconcreteumtabledata appendBytes:length://code>

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

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

编辑:进一步的调查显示,当我使用
[request release]
时,请求对象被释放,但它的主体没有被释放。很奇怪的行为


EDIT2:我明确使用了
[request.HTTPBody release]和字节被释放。我仍然不能相信
[请求释放]
没有释放它的身体。这可能是一个bug吗?

您的请求有一个
重新计数
为2:

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

然后,如果您执行
[请求释放]
,它将减少1


解决方案是不执行
[请求保留]

您的请求的
保留计数为2:

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

然后,如果您执行
[请求释放]
,它将减少1


解决方案是不执行
[request retain]
进一步调查后,内存没有释放,因为请求的属性
HTTPBody
需要手动释放(请参阅我的第二次编辑)


至于在
NSRequest
中发送大块数据,有一种更简单的方法不会占用设备内存。您必须将文件写入磁盘,然后映射它。我已在本报告中详细说明了这一点。希望对某人有所帮助

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


至于在
NSRequest
中发送大块数据,有一种更简单的方法不会占用设备内存。您必须将文件写入磁盘,然后映射它。我已在本报告中详细说明了这一点。希望它能帮助别人

我完全同意你的看法。我删除了retain,但仍然没有释放内存。有什么想法吗?你还忘了调用
free(缓冲区)
。苹果的文档说,
freeWhenDone:是的
应该会处理好的。没问题,我的朋友,我真的非常感谢你的帮助。看我在问题中的编辑,我明白了发生了什么,注意绝对重新计算是不相关的;它可能是也可能不是@kovpass所声称的(而且很可能不会在请求中使用URL)。关键是你必须在释放对象之前平衡保留和释放。我完全同意你的观点。我删除了retain,但仍然没有释放内存。有什么想法吗?你还忘了调用
free(缓冲区)
。苹果的文档说,
freeWhenDone:是的
应该会处理好的。没问题,我的朋友,我真的非常感谢你的帮助。看我在问题中的编辑,我明白了发生了什么,注意绝对重新计算是不相关的;它可能是也可能不是@kovpass所声称的(而且很可能不会在请求中使用URL)。关键是你必须在释放对象之前平衡保留和释放。你不使用ARC有什么原因吗?我个人很想使用ARC,但所有者指定我们不能使用它为什么?兼容性甚至不再是一个好的理由。你不使用ARC有什么原因吗?我个人很想使用ARC,但所有者指定我们不能使用它为什么?兼容性甚至不再是一个好理由。