NSMutableData如何分配内存?

时间:2010-08-02 11:03:52

标签: objective-c memory-management error-handling

当我运行以下代码时,它会慢慢耗尽我的记忆,甚至开始使用swap:

 long long length = 1024ull * 1024ull * 1024ull * 2ull; // 2 GB

 db = [NSMutableData dataWithLength:length];

 char *array = [db mutableBytes];

 for(long long i = 0; i < length - 1; i++) {
      array[i] = i % 256;
 }

如果我在没有for循环的情况下运行它,则根本不使用内存:

 long long length = 1024ull * 1024ull * 1024ull * 2ull;
 db = [NSMutableData dataWithLength:length];
 char *array = [db mutableBytes];
 /* for(long long i = 0; i < length - 1; i++) {
      array[i] = i % 256;
 } */

我只能得出结论,NSMutableData只是“保留”内存,当它被访问时,它真正“分配”它。它是如何完成的?

这是通过硬件(CPU)完成的吗?

NSMutableData是否有办法在其“保留”内存中捕获内存写入,然后才进行“分配”?

这是否意味着对[NSMutableData dataWithLength:length]的调用永远不会失败?如果需要,它可以使用swap分配任何大小的内存吗?

如果它可以失败,我的db变量是否为null?

在Apple的“NSMutableData Class Reference”中,我只看到关于这些主题的模糊句子。

1 个答案:

答案 0 :(得分:6)

这不是NSMutableData问题,而是内核/操作系统问题。如果进程请求(大)内存块,内核通常只会说“没关系,这里就去了”。但只有实际使用它,它才真正(“物理上”)分配。这是好的,因为如果你的程序以2 GB malloc开头(正如你在这里做的那样),它会立即推出其他程序进行交换,而在实践中你通常不会立即使用2 GB。

当访问物理内存中实际不存在的内存页时,内核将从CPU获取信号。如果页面应该在那里(因为它在你的2 GB块内)它将被放置到位(可能来自交换),你甚至不会注意到。如果页面不在那里(因为地址未在虚拟内存中分配),您将收到分段错误(SIGSEGV或EXC_BAD_ACCESS类错误)。

其中一个相关主题是“overcommit(ment)”,其中内核承诺的内存比实际可用内存多。如果所有进程都开始使用其承诺的内存,则可能会导致严重问题。这取决于操作系统。

互联网上有很多页面更好更详细地解释这一点;我只是想简短地介绍一下,以便你有条款放入谷歌。

编辑刚刚测试过,linux会很容易地向我承诺4 TB的内存,而 - 我向你保证 - 该机器中总共没有1 TB的磁盘存储空间。您可以想象,如果不加以处理,在构建关键任务系统时会引起一些麻烦。