我应该在应用程序终止时处理泄漏,还是让系统处理它们更有效?我认为系统无论如何都会回收所有的内存,所以不会有额外的努力来解决它的开销吗?
答案 0 :(得分:3)
引用paxdiablo:
我所知道的所有操作系统都将回收已分配的常规内存。这是因为分配通常来自进程私有地址空间,将在退出时回收。
据我所知,这也适用于iOS。
然而,Apple可能拒绝您的申请。单独的内存泄漏通常没有理由拒绝应用程序,但它们可能是导致存储桶溢出的丢弃。适当的内存管理是很好的做法,应该始终如一。答案 1 :(得分:2)
当您的应用终止时,没有理由尝试释放所有内存。
这样做会浪费CPU周期。
当然,您可能需要一个“关闭”阶段,该阶段会持续某个状态,但您的代码也必须假设“关闭”代码路径可能无法运行。
当应用程序终止时,系统将回收应用程序分配的所有资源,无论其如何终止。
事实上,UIKit(iOS)和AppKit(OS X)在应用程序终止时都会占用大量快捷方式,这会导致在应用程序终止时仍然分配大量内存。这完全是出于回应的原因;当用户请求退出应用时,它应该很快退出。
(我真的不能想到现代的多任务,任务隔离,操作系统不能自动回收进程终止的资源。)
答案 2 :(得分:1)
所有应用程序(进程)都在自己的私有内存空间中运行。操作系统对此进行管理,并始终确切地知道已为该进程分配了什么“物理”内存。当进程退出时,它能够完全恢复所有已用内存。
因此,如果您的应用程序要退出,则不需要进行任何内存管理或清理(文件访问或网络连接等也是如此,但在这些情况下,它可能符合您的最佳利益)清理)。
但是,您的应用程序永远不应“泄漏”内存。
当您分配一块内存然后在正在运行的程序中丢失对它的所有引用时,就会出现泄漏。
单身不是泄漏,仪器不会将其标记为泄漏。
所以,如果你有这样的事情:
static NSString *aStaticString = nil;
+ (void)aFunction {
aStaticString = [[NSString alloc] initWithString:@"aFunction"];
}
这不是泄漏。所以假设你还有另一个功能:
+ (void)anotherFunction {
aStaticString = [[NSString alloc] initWithString:@"anotherFunction"];
}
现在,假设您正在使用ARC,调用这些函数不会导致泄漏。编译器/运行时知道管理NSString分配,并且当aStaticString变量更改时,释放旧内存。
所以考虑到这一点,你怎么得到泄漏?通常它将由于循环引用。例如:
+ (void)aBadFunction {
NSMutableDictionary *aDict = [[NSMutableDictionary alloc] init];
[aDict addObject:aDict forKey:@"aCircularReference"];
}
这里,创建(分配)aDict,然后向其添加对自身的引用。当函数返回时,内存会泄漏,因为程序不再对aDict变量有任何引用(如果再次调用该函数,将创建一个新的完全不同的aDict变量)。现在通常ARC会确保在函数退出时取消分配aDict,但在这种情况下它不能,因为在对象本身中有的引用。
通常这样的循环引用更复杂,但原理是相同的。
答案 3 :(得分:0)
你应该总是释放记忆,但是,请参阅下面的评论:
之间有区别:
int main() {
int* i = malloc(5);
... // do stuff here
return 0; // i "leaked" here, not that serious, a lot of programmers will skip freeing `i` before return
}
和
int main() {
int* i;
for(int j = 0; j < 5000; j++)
i = malloc(5); // you leaked 5 bytes 5000 times, very serious, DO NOT DO THIS
// the 24KB here will most likely be reclaimed later, HOWEVER
// what if j changes? what if you have more loops? you may run of memory, especially on an embedded device!
... // do stuff here
return 0;
}
只需遵循一条规则:在处理正确的C内存管理(C编码约定)时,永远不要担心开销。
这样做:
int main() {
int* i;
for(int j = 0; j < 5000; j++) {
i = malloc(5);
... // do stuff with i here
free(i); // you are not leaking anything =D
}
... // do stuff here
return 0;
}