Objective c 应用程序终止时泄漏

Objective c 应用程序终止时泄漏,objective-c,ios,c,memory-management,memory-leaks,Objective C,Ios,C,Memory Management,Memory Leaks,我应该在应用程序终止时处理泄漏,还是让系统处理泄漏更有效?我认为系统无论如何都会回收所有内存,因此释放内存的额外工作不会是开销吗?引用: 我所知道的所有操作系统都将回收已分配的常规内存。这是因为分配通常来自进程的私有地址空间,该地址空间将在退出时回收 据我所知,这也适用于iOS 苹果可能会拒绝你的申请。内存泄漏本身通常不是拒绝应用程序的理由,但它们可能是导致存储桶溢出的原因。正确的内存管理是一种良好的做法,应该始终坚持。不过,您应该始终释放内存,请参见下面的注释: 这两者之间有区别: int m

我应该在应用程序终止时处理泄漏,还是让系统处理泄漏更有效?我认为系统无论如何都会回收所有内存,因此释放内存的额外工作不会是开销吗?

引用:

我所知道的所有操作系统都将回收已分配的常规内存。这是因为分配通常来自进程的私有地址空间,该地址空间将在退出时回收

据我所知,这也适用于iOS


苹果可能会拒绝你的申请。内存泄漏本身通常不是拒绝应用程序的理由,但它们可能是导致存储桶溢出的原因。正确的内存管理是一种良好的做法,应该始终坚持。不过,您应该始终释放内存,请参见下面的注释:

这两者之间有区别:

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

}
以及:

intmain(){
int*i;
对于(int j=0;j<5000;j++)
i=malloc(5);//您泄漏了5000次5字节,非常严重,不要这样做
//不过,此处的24KB很可能稍后会被回收
//如果j改变了怎么办?如果你有更多的循环怎么办?你可能会耗尽内存,尤其是在嵌入式设备上!
…//在这里做事
返回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;
}
intmain(){
int*i;
对于(int j=0;j<5000;j++){
i=malloc(5);
…//在这里和我一起做事
free(i);//你没有泄漏任何东西=D
}
…//在这里做事
返回0;
}
所有应用程序(进程)都在自己的专用内存空间中运行。操作系统对此进行管理,并始终准确地知道已分配给进程的“物理”内存。当进程退出时,它能够完全恢复所有已使用的内存

因此,如果您的应用程序要退出,您不需要进行任何内存管理或清理(对于文件访问或网络连接等情况也是如此,但在这些情况下,清理可能是您的最佳利益)

但是,您的应用程序不应该“泄漏”内存

泄漏是指分配一块内存,然后在正在运行的程序中丢失对它的所有引用。

单件不是泄漏,仪器不会将其标记为泄漏

所以,如果你有这样的东西:

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被解除分配,但在这种情况下它不能,因为在对象本身中有对它的引用


一般来说,像这样的循环引用比较复杂,但原理是一样的。

当应用程序终止时,没有理由尝试释放所有内存。

这样做是对CPU周期的浪费

当然,您可能需要一个“shutdown”阶段来保持某种状态,但是您的代码还必须假定“shutdown”代码路径可能没有运行

当应用程序终止时,系统将回收应用程序分配的所有资源,无论应用程序如何终止

事实上,UIKit(iOS)和AppKit(OSX)在应用程序终止期间都会采用许多快捷方式,这导致应用程序终止时仍会分配大量内存。这完全是出于响应性的原因;当用户请求退出某个应用程序时,它应该很快退出


(我真的想不出一个现代的多任务、任务隔离的操作系统在进程终止时不会自动回收资源。)

我相信系统只有在内存泄漏时才会回收内存。如果您的应用程序已返回所获取的所有资源,那么系统将无所事事。因此,没有开销。在事后如何处理泄漏?泄漏之所以称为泄漏,是因为您无法收回对丢失内存位置的原始引用——“引用泄漏出去”。@jsn,我无法处理它们,但我可以以不产生泄漏的方式更新代码。它们当前的产生是因为我只需要在应用程序的生命周期中使用一些单例。@Mahesh,但是如果应用程序退出,那么系统应该简单地将其所有内存标记为空闲,而我没有任何额外的周期来做这件事,不是吗?@Radu单例不会以任何方式、形状或形式导致泄漏。的确,这就是问题所在,这是正确的内存管理实践。正如jsn在评论中指出的,开销应该是最小的。所谓“适当的内存管理”,我的意思是在执行和/或退出期间不会发生泄漏。适当的内存管理是良好编程技能的特征,开发人员知道他/她在做什么。在审查期间,我通常坚持修复严重的内存泄漏。开销确实很小。那么,如何处理终止后的单身问题呢?@Anne,我完全同意每个人都应该遵循最佳实践。就我而言,它实际上只是一行代码。我只是想知道应该做什么——免费还是不免费。我会自由的。我想我曲解了我代码中的“漏洞”。。。我正在分配一些内存
+ (void)aBadFunction {
    NSMutableDictionary *aDict = [[NSMutableDictionary alloc] init];
    [aDict addObject:aDict forKey:@"aCircularReference"];
}