Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 在main()中省略@autoreleasepool{}会有什么后果?_Objective C_Macos_Memory Management_Clang - Fatal编程技术网

Objective c 在main()中省略@autoreleasepool{}会有什么后果?

Objective c 在main()中省略@autoreleasepool{}会有什么后果?,objective-c,macos,memory-management,clang,Objective C,Macos,Memory Management,Clang,为什么Objective-C命令行和iOS程序的Xcode 4.x模板添加了@autoreleasepool{}部件包装main()的代码?请注意,OSX应用程序模板不会发生这种情况 为什么OSX应用程序不这样做?为什么两者不使用相同的方法 最后,由于任何程序退出时都会释放所有内存,为什么所有这些都是实用的 或者换一种说法,对于命令行或iOS Objective-C程序,在main()中省略@autoreleasepool{…}的实际后果是什么 这两段代码可以编译,并且似乎可以等效地工作: 一

为什么Objective-C命令行和iOS程序的Xcode 4.x模板添加了
@autoreleasepool{}
部件包装
main()
的代码?请注意,OSX应用程序模板不会发生这种情况

为什么OSX应用程序不这样做?为什么两者不使用相同的方法

最后,由于任何程序退出时都会释放所有内存,为什么所有这些都是实用的


或者换一种说法,对于命令行或iOS Objective-C程序,在
main()
中省略
@autoreleasepool{…}
的实际后果是什么

这两段代码可以编译,并且似乎可以等效地工作:

一,

二,



注意,我只关心ARC上下文中的解释。ARC禁止显式使用
自动释放

在上面的代码示例中,您没有使用任何自动释放的对象

但是,如果你在做这样的事情:

NSString * somethingToSay = [NSString stringWithString:@"this is an autoreleased string, believe it or not"];
NSLog(@"%@", somethingToSay);
return 0;
@autoreleasepool
”位实际上更有用

,他们说:

在自动释放池块的末尾,接收到 块内的自动释放消息发送一条释放消息 对象每次发送释放消息时都会收到一条释放消息 块内的自动释放消息

因此,当您有很多自动释放的对象时(您可以创建很多对象,这些对象最终成为NSArray、NSDictionary、NSString等),这些自动释放池有助于释放内存


应用程序模板在main.m中包含“
@autoreleasepool
”,因为在iPhone或iPad等设备上,内存使用至关重要,我们希望确保在应用程序退出“
UIApplicationMain
”时,所有内存都得到正确释放(不太可能,因为大多数人都会让iPhone应用程序一直运行到重新启动,但这种情况可能会发生)。

autorelease
如果堆栈上没有自动释放池,则无法工作

在objective-c中没有必要使用自动释放对象(正如您在示例中所做的那样),因此理论上可以省略它,但是大多数Apple框架确实大量使用自动释放对象

通常,每个线程都应该至少有一个自动释放池,否则使用任何Obj-C代码都是非常不安全的。在
main
的开头设置自动释放池是一个非常好的做法

编辑:

在ARC中,虽然禁止显式的
autorelease
,但是仍然存在
autorelease
调用(由编译器添加)。这意味着需要一个autorelease池

这与释放内存无关。自动释放池的存在是必要的,即使它从未耗尽

我猜OSX没有将自动释放池添加到模板中,因为程序员也可以使用垃圾收集器(尽管现在不推荐使用)

编辑2:

刚刚创建了一个OSX项目,并且有
@autoreleasepool
。事实上,没有它的唯一模板是一个“核心基础”项目,它不是真正的Obj-C,它是纯C

编辑3:(经过一些思考和谷歌搜索)

随着ARC的引入,自动释放池被重写。以前它们是一种框架特性,现在它们是一种语言(Obj-C)功能。它们的实现方式不同。现在似乎每个新线程都有一个隐式自动释放池。使用
@autoreleasepool
实际上不再在某个线程堆栈上创建新的自动释放池,它只是在隐式自动释放池中添加一个标记(这样您就可以在标记后耗尽所有自动释放的内容)。这意味着在省略
@autoreleasepool
时,无法创建触发警告或错误的示例


但是,这被认为是一个实现细节,因此在将来(或使用其他编译器时!)可以很容易地对其进行更改。这就是为什么最好还是为每个新线程设置一个
@autoreleasepool
(例如,在
-[NSThread detachWithSelector:…]
文档中提到).

您需要它,因为文档上说您需要它。这应该足够了,相信文档:

通常,您不需要创建自己的自动释放池块,但在某些情况下,您必须这样做,或者这样做是有益的

Cocoa总是希望代码在自动释放池中执行 块,否则自动释放的对象不会被释放,并且 应用程序内存泄漏。(如果您在外部发送自动释放消息。) 对于自动释放池块,Cocoa会记录适当的错误消息。)

…但是,在三种情况下,您可能会使用自己的自动释放池块:

  • 如果您正在编写一个不基于UI框架的程序,例如命令行工具

如果您正在编写仅限Foundation的程序或分离线程,则需要创建自己的自动释放池块

如果没有自动释放池…那么大多数事情仍然可以正常工作,但它是“大多数”事情,而不是“所有”事情。它们只说明了两个原因,但是可能还有其他原因没有记录,并且所有这些行为都可能在将来的任何时候发生变化


如果您遵循推荐的最佳实践,那么您的代码在20年后仍然可以正常运行,但如果您不这样做,从下一次x.x.x操作系统更新开始,每50次执行中可能会随机崩溃一次。

苹果文档中的这句话可能会有所帮助:

如果分离的线程不进行Cocoa调用,则不需要使用自动释放池块

这可以推断为
int main(int argc, const char * argv[])
{
    NSArray *array = @[@"Hello, world!"];
    NSLog(@"%@", array[0]);
}
NSString * somethingToSay = [NSString stringWithString:@"this is an autoreleased string, believe it or not"];
NSLog(@"%@", somethingToSay);
return 0;