Gyo*_*par 4 error-handling memory-management objective-c
当我运行以下代码时,它会慢慢占用我的内存,甚至开始使用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;
}
Run Code Online (Sandbox Code Playgroud)
如果我在没有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;
} */
Run Code Online (Sandbox Code Playgroud)
我只能得出结论,NSMutableData只是"保留"内存,当它被访问时,它真的"分配"它.它是如何完成的?
这是通过硬件(CPU)完成的吗?
有没有办法让NSMutableData在其"保留"内存中捕获内存写入,然后才进行"分配"?
这是否意味着呼叫[NSMutableData dataWithLength:length]永远不会失败?如果需要,它可以使用swap分配任何大小的内存吗?
如果它可以失败,我的db变量是否为null?
在Apple的"NSMutableData Class Reference"中,我只看到了关于这些主题的模糊句子.
这不是NSMutableData问题,而是内核/操作系统问题.如果进程请求(大)内存块,内核通常只会说"没关系,这里就去了".但只有实际使用它,它才真正("物理上")分配.这是好的,因为如果你的程序以2 GB的malloc开头(就像你在这里做的那样),它会立即推出其他程序进行交换,而实际上你通常不会立即使用2 GB.
当访问实际上不存在于物理内存中的内存页时,内核将从CPU获取信号.如果页面应该在那里(因为它在你的2 GB块内)它将被放置到位(可能来自交换),你甚至不会注意到.如果页面不在那里(因为地址未在虚拟内存中分配),您将收到分段错误(SIGSEGV或EXC_BAD_ACCESS类错误).
其中一个相关主题是"overcommit(ment)",其中内核承诺的内存比实际可用内存多.如果所有进程都开始使用其承诺的内存,则可能会导致严重问题.这取决于操作系统.
互联网上有很多页面更好,更详细地解释了这一点; 我只是想简短介绍一下你有条款放在谷歌.
编辑刚刚测试过,linux会很容易地向我承诺4 TB的内存,而 - 我向你保证 - 该机器的总磁盘存储量甚至不到1 TB .您可以想象,如果不加以处理,在构建关键任务系统时可能会引起一些麻烦.