objective-c - NSMutableData 是如何分配内存的?

标签 objective-c memory-management error-handling

当我运行以下代码时,它会慢慢耗尽我的内存,甚至开始使用交换:

 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] 的调用永远不会失败?如果需要,它可以使用交换分配任意大小的内存来获取它吗?

如果失败,我的 db 变量是否为空?

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

最佳答案

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

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

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

互联网上有很多页面对此进行了更好、更详细的解释;我只是想做一个简短的介绍,这样你就可以在谷歌中输入条款了。

编辑 刚刚测试过,linux 很容易向我 promise 4 TB 的内存,而 - 我向你保证 - 该机器中的总磁盘 存储空间甚至不到 1 TB .您可以想象,如果不注意这一点,可能会在构建关键任务系统时引起一些麻烦。

关于objective-c - NSMutableData 是如何分配内存的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3387090/

相关文章:

error-handling - 如何处理 nuxtjs 插件中的 axios onError 并向用户显示适当的错误消息

objective-c - 使用openssl编译报错

objective-c - 从 XCode 调用本地 HTML 文件时出现问题

ios - 使用宏检测 iPhone X

java - 卡片布局与内存效率

bash - 如果脚本调用的shell脚本产生错误,如何将其破坏

c# - Webforms应用程序中的ASP.NET 3.5 C#自定义错误页面

c++ - Objective-C block 和 C++ 对象

c - C链表遍历中移除条目并释放桶节点时出错

c++ - 是否可以在运行时在堆上创建一个数组,然后在需要时分配更多空间?