如果我有这段代码
NSString *postData = [@"foo=" stringByAppendingString:fooText.text];
...
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
...
[postData release]; //this causes crash
[request release]; //this causes crash
现在我明白这是expected behavior according to Apple's documents。现在,如果我删除释放代码,崩溃不会发生,但我发现内存泄漏无论如何为*请求。所以我重写了代码
NSString *postData;
//postData = [NSString alloc]; // this line commented out since OP
postData = [@"foo=" stringByAppendingString:fooText.text];
...
NSMutableURLRequest *request;
request = [NSMutableURLRequest alloc];
request = [request initWithURL:url];
...
[postData release]; //this still crashes #
[request release]; //this works fine
我真的不明白为什么它会在#崩溃。这里有推荐的最佳做法吗?我认为我必须遗漏一些东西,因为我经常看到“速记”方法(顶部)有一个版本(例如Kochan,Objective-C编程),但Apple文档说这是错误的。
答案 0 :(得分:7)
一般的经验法则,如果你正在调用辅助静态方法(例如stringByAppendingString
),那么就不应该释放它。在给予您之前,该字符串已添加到自动释放池中。如果您正在调用alloc
然后调用init...
方法,那么您有责任释放该对象。
您的代码中需要注意的其他事项:
stringByAppendingString
创建的另一个字符串,即内存泄漏。[postData release]
和[request release]
postData
和request
之间存在任何关联,因此不确定您对这两者的确切了解。答案 1 :(得分:1)
首先,在第二个示例中,行postData = [NSString alloc];
完全没必要 - postData
会被下一行覆盖。第二,回答关于为什么事情崩溃的问题 - 没有好的答案 - 系统可以选择在保留计数达到0后随时释放内存。为了更容易地调试问题,你应该打开NSZombieEnabled ,它将立即乱写任何已解除分配的对象,为您提供100%可靠的测试崩溃方法。
另外,在单独的行上分配/ init是不好的风格。
通常,您应该专注于遵循内存准则。如果您不遵守这些准则,则行为可能未定义。
答案 2 :(得分:0)
为您的对象分配内存并初始化它更好地执行单行 - init方法可能会返回不同的对象,也可能有助于避免您在第二个示例中犯的错误:
NSString *postData; // Define pointer to string
postData = [NSString alloc]; // Allocating nsstring pointer and assign it to variable
postData = [@"foo=" stringByAppendingString:fooText.text]; // assign to postData new **autoreleased** string object. result of the previous assignment is abandoned.
[postData release]; //so here you release autoreleased object!!
我无法弄清楚为什么[equest release];但是在第一个例子中导致崩溃。
P.S。我没有完全醒来,或者它应该是[postData release]
而不是[release postData]
?
答案 3 :(得分:-1)
NSString *postData;
postData = [[NSString alloc]init];
postData = [@"foo=" stringByAppendingString:fooText.text];
...
NSMutableURLRequest *request;
request = [[NSMutableURLRequest alloc]initWithURL:url];
...
[postData release];
[request release];
试试这个。