错误在创建后自动释放对象

时间:2011-09-02 10:32:19

标签: ios nsurlconnection autorelease nsurlrequest

我开始研究IOS开发,我对发布没有存储引用的对象有一些疑问。我看了一下“释放一个没有指针的对象?”的问题。建议在创建对象后立即向对象发送自动释放消息,因此我尝试在下面的代码中执行相同的操作:

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data;

    data = [NSURLConnection
            sendSynchronousRequest: [[NSURLRequest requestWithURL: 
                                        [[NSURL URLWithString: @"http://www.google.it"] 
                                          autorelease] 
                                     ] autorelease]
                 returningResponse: &response
                             error: &error];

    [data writeToFile: @"/tmp/test.html"
           atomically:NO];

    [data release];
    [pool drain];

    return 0;
}

我还没有尝试在XCode中执行程序,但是我在linux下编译并且发送到NSURLRequest对象的自动释放消息导致了分段错误(我认为它不是由消息本身引起的,而是由池引起的由于自动释放消息,尝试释放对象的排水)。我发送给NSURLRequest对象的自动释放消息有什么问题?

我认为如果像requestWithUrl这样的类方法的引用文档说它“创建并返回一个URL请求”,则意味着我负责在我使用它时释放该对象,我错了吗?在进一步研究其他任何事情之前,我想非常了解这个内存管理规则。我希望我的问题不是太愚蠢;-)

呃,还有最后一个问题:我是否应该同时发布同步请求返回的错误和数据对象?

提前感谢您的帮助!

4 个答案:

答案 0 :(得分:3)

+requestWithURL:(以及其他)方法已经返回自动释放的对象,因此您不应再向其发送一次自动释放。

代码中的额外自动释放会使对象过度释放并使应用程序崩溃。

要知道是否必须释放对象的经验法则 - 只有在使用名称中包含“alloc”,“new”,“copy”的方法创建对象时才需要释放。所有标准API都遵循此规则,您应该在开发自己的方法时遵循它。

如此纠正的代码将是:

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data;

    data = [NSURLConnection
            sendSynchronousRequest: [NSURLRequest requestWithURL: 
                                            [NSURL URLWithString: @"http://www.google.it"]                                                                                
                 returningResponse: &response
                             error: &error];

    [data writeToFile: @"/tmp/test.html"
           atomically:NO];

    [pool drain];

    return 0;
}

P.S。出于上述原因,不应释放数据和错误对象。

答案 1 :(得分:1)

您的代码应如下所示:

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data;

    data = [NSURLConnection
            sendSynchronousRequest: [NSURLRequest requestWithURL:[NSURL URLWithString: @"http://www.google.it"]] returningResponse:&response error: &error];

    [data writeToFile: @"/tmp/test.html"
           atomically:NO];

    [pool drain];

    return 0;
}

您无需向使用该方法创建的对象调用autorelease。\

您无需发布dataerror

使用下一个符号NSClass *object = [NSClass classSomeMagicWords];返回对象的所有方法都将返回自动释放的对象,如果不调用retain,则不应释放该对象。

答案 2 :(得分:0)

你应该删除自动释放。在iOS / Mac OSX开发中,使用Apple提供的类,几乎可以规定,如果使用不涉及单词init的方法创建对象,则会给出一个已经自动释放的对象。

例如:

NSString *blaah = [[NSString alloc] init];

将返回稍后需要释放的对象。

NSURL *googlelink = [NSURL URLWithString: @"http://www.google.it"];
另一方面,

将为您提供一个自动释放的对象,如果再次释放它,它将崩溃。

答案 3 :(得分:0)

在iOS内存管理中,您只拥有通过为其分配内存或复制它而创建的对象(方法以alloc开头或名称中包含“copy”)。

如果您拥有它们,则只需要释放/自动释放它们。 requestWithURLURLWithString等方法返回已自动释放的对象。

从Apple开发者网站查看this doc以获取更多信息。