Iphone iOS:理解NSString的发布问题

Iphone iOS:理解NSString的发布问题,iphone,ios,exception,exc-bad-access,Iphone,Ios,Exception,Exc Bad Access,我有以下代码: + (NSDictionary*) JSONRequest: (NSString*)query andWithCredentials:(BOOL)withCredentials { if (withCredentials) { NSString *username = [LoginHandler GetUsernameFromNSDefaults]; NSString *password = [LoginHandler GetPasswordFromNSDefau

我有以下代码:

+ (NSDictionary*) JSONRequest: (NSString*)query andWithCredentials:(BOOL)withCredentials
{
if (withCredentials)
{
    NSString *username = [LoginHandler GetUsernameFromNSDefaults];
    NSString *password = [LoginHandler GetPasswordFromNSDefaults];
    NSString *additionalQuery = [NSString stringWithFormat:@"login_username=%@&login_password=%@", username, password];

    query = [NSString stringWithFormat:@"%@&%@", query, additionalQuery];

    [username release];
    [password release];
    [additionalQuery release]; 
}

NSURLRequest *request = [NSURLRequest requestWithURL:  
                         [NSURL URLWithString:query]];  

NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

NSString *jsonString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *results = [jsonString JSONValue];
return results;

[request release];
[response release];
[jsonString release];
[results release];

}
问题在于additionalQuery NSString的发布。 当我运行此代码时,它以

[additionalQuery release];
只要我把它注释掉,代码就可以正常工作

现在,简单地说,不使用这行代码运行我的应用程序是可以的,但我的问题是:我做错了什么


我在IF子句中生成NSString,然后只能在IF子句中释放它。但是为什么我在那里出错?

您在这里指定了[NSString stringWithFormat:@“login\u username=%@&login\u password=%@”,username,password]

表示此方法将处理字符串的分配和释放,因此“您不需要释放它”,因此删除行[additionalQuery release]

此外,u没有为用户名和密码分配字符串,因此不需要释放它

如果您编写Nsstring*username=[[Nsstring alloc]init];然后你需要释放它

有关内存管理的更多信息,请参阅


这将真正帮助您…

您在此处指定了[NSString stringWithFormat:@“login_username=%@&login_password=%@”,username,password]

表示此方法将处理字符串的分配和释放,因此“您不需要释放它”,因此删除行[additionalQuery release]

此外,u没有为用户名和密码分配字符串,因此不需要释放它

如果您编写Nsstring*username=[[Nsstring alloc]init];然后你需要释放它

有关内存管理的更多信息,请参阅


这将真正帮助您……

您不必手动释放它,它将自动释放。(
[NSString stringWithFormat:
vs.
[NSString initWithString:

您不必手动释放它,它将自动释放。(
[NSString stringWithFormat:
vs.
[NSString initWithString:

我可以看到,附加查询从未被保留。(
stringWithFormat
执行自动释放,因此它不起作用。)

我可以看到,附加查询从未被保留。(
stringWithFormat
执行自动释放,因此不计算在内。)

查看您创建的附加查询

NSString *additionalQuery = [NSString stringWithFormat:@"login_username=%@&login_password=%@", username, password];
使用stringWithFormat可以创建自动删除的NSString对象。您不能根据内存管理规则手动释放它,因为您不拥有它

您只拥有使用alloc]init..创建的东西或使用new.创建的东西。。或创建。。当然,如果你做了一个拷贝,比如mutableCopy


因此[additionalQuery release]会导致过度释放对象,因此这是一个错误的访问

看看您创建的additionalQuery

NSString *additionalQuery = [NSString stringWithFormat:@"login_username=%@&login_password=%@", username, password];
使用stringWithFormat可以创建自动删除的NSString对象。您不能根据内存管理规则手动释放它,因为您不拥有它

您只拥有使用alloc]init..创建的东西或使用new.创建的东西。。或创建。。当然,如果你做了一个拷贝,比如mutableCopy


因此[additionalQuery release]会导致过度释放对象,因此,当您使用方便的方法(不以new、alloc或copy开头的方法)创建对象的实例时,返回的对象会自动释放,这是一个错误的访问。换句话说,您不需要显式地释放它

调用stringWithFormat方法时,它将返回一个自动删除的NSString。您随后将继续释放此NSString实例

[additionalQuery release];
这会将释放消息发送到additionalQuery实例。由于它是一个自动释放对象,所以它被添加到(通常)位于主事件线程上的自动释放池中。这个池经常被清空,然后向它包含的每个对象发送一条释放消息。因此,当一个对象被自动释放时,池将负责为您发送释放消息


这里的EXC_BAD_访问是您释放NSString的结果—在池排空之前将其保留计数降至0。然后,池被排空并尝试向解除分配的对象发送消息。

当您使用方便的方法(不以new、alloc或copy开头的方法)创建对象实例时,返回的对象将自动删除。换句话说,您不需要显式地释放它

调用stringWithFormat方法时,它将返回一个自动删除的NSString。您随后将继续释放此NSString实例

[additionalQuery release];
这会将释放消息发送到additionalQuery实例。由于它是一个自动释放对象,所以它被添加到(通常)位于主事件线程上的自动释放池中。这个池经常被清空,然后向它包含的每个对象发送一条释放消息。因此,当一个对象被自动释放时,池将负责为您发送释放消息


这里的EXC_BAD_访问是您释放NSString的结果—在池排空之前将其保留计数降至0。然后耗尽池并尝试向解除分配的对象发送消息。

问题是字符串实例是使用以类名(
stringWithFormat
)开头的类方法创建的。按照惯例,这些类型的类方法返回一个自动释放的对象,这样您就不用担心释放它们,除非您专门对返回的对象调用retain

如果确实要对对象执行自己的内存管理,可以更改行:

NSString *additionalQuery = [NSString stringWithFormat:
    @"login_username=%@&login_password=%@", username, password];
以下任何一项:

NSString *additionalQuery = [[NSString alloc] initWithFormat:
    @"login_username=%@&login_password=%@", username, password];
或:


顺便说一句,这段代码还有其他几个问题

  • 不应释放
    username
    变量,因为按照惯例,从
    GetUsernameFromNSDefaults
    获取该变量的方法应返回自动释放的对象。作为一般经验法则,除了代码以外的任何方法