Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.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
Macos 在Mac OS X上,中等大小的内存分配如何在64位进程中失败?_Macos_64 Bit_Memory Management_Nsdata - Fatal编程技术网

Macos 在Mac OS X上,中等大小的内存分配如何在64位进程中失败?

Macos 在Mac OS X上,中等大小的内存分配如何在64位进程中失败?,macos,64-bit,memory-management,nsdata,Macos,64 Bit,Memory Management,Nsdata,我正在构建一个相册布局应用程序。该应用程序经常将JPEG图像解压缩到内存位图缓冲区中。图像的大小被限制为1亿像素(而它们通常不超过1500万像素) 有时这些缓冲区的内存分配失败:[[NSMutableData alloc]initWithLength:返回nil。这似乎发生在系统的可用物理内存接近零的情况下 我的理解是,64位进程(sic)中的分配实际上不会失败。有16 EB的地址空间,我试图一次最多分配400 MB。理论上,我可以分配400亿个这样的缓冲区,而不会达到可用地址空间的硬限制。当然

我正在构建一个相册布局应用程序。该应用程序经常将JPEG图像解压缩到内存位图缓冲区中。图像的大小被限制为1亿像素(而它们通常不超过1500万像素)

有时这些缓冲区的内存分配失败:
[[NSMutableData alloc]initWithLength:
返回
nil
。这似乎发生在系统的可用物理内存接近零的情况下

我的理解是,64位进程(sic)中的分配实际上不会失败。有16 EB的地址空间,我试图一次最多分配400 MB。理论上,我可以分配400亿个这样的缓冲区,而不会达到可用地址空间的硬限制。当然,实际限制会阻止这种情况,因为交换空间受到启动卷大小的限制。事实上,我只做了很少的这些分配(少于10)

我不明白的是,无论此时的物理内存有多低,分配都会失败。我认为只要有交换空间,内存分配就不会失败(因为此时页面甚至没有映射)

应用程序被垃圾收集

编辑:

我有时间进一步研究这个问题,以下是我的发现:

  • 该问题仅发生在垃圾收集过程中
  • 当从
    NSMutableData
    分配失败时,普通
    malloc
    仍能成功分配相同数量的内存
  • 当整个物理内存接近零时(交换即将发生),错误总是会发生
  • 我假设在垃圾收集下运行时,
    NSData
    使用
    NSAllocateCollectable
    执行分配,而不是
    malloc


    我的结论是,当物理内存不足时,收集器无法分配大块内存。同样,我也不明白。

    即使64位计算机理论上可以处理18EB,但当前的处理器限制在256TB。当然,你也没有达到这个极限。但您的进程一次可以使用的内存量仅限于可用的RAM量。操作系统还可能限制您可以使用的RAM数量。根据您发布的链接,“即使对于具有4 GB或更多可用RAM的计算机,系统也很少将这么多RAM用于单个进程。”

    initWithBytes:length:
    尝试在活动内存中分配其整个长度,基本上相当于该大小的
    malloc()
    。如果长度超过可用内存,您将得到零。如果您想使用带有
    NSData
    的大型文件,我建议使用
    initWithContentsOfMappedFile:
    或类似的初始值设定项,因为它们使用VM系统在需要时将部分文件拉入和拉出活动内存。

    您可能会耗尽交换空间。即使您有交换文件和虚拟内存,可用交换空间的大小仍然受到交换文件硬盘空间的限制。

    这可能是内存碎片问题。也许在分配时没有任何400 MB的连续块可用


    您可以在应用程序生命周期的一开始就尝试分配这些大数据块,以免堆被大量较小的分配分割。

    另一种猜测是,您同事的机器配置了更严格的每个用户进程最大内存设置。要检查,请键入

    ulimit-a

    进入控制台。对我来说,我得到:

    ~ iainmcgin$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) unlimited max memory size (kbytes, -m) unlimited open files (-n) 256 pipe size (512 bytes, -p) 1 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 266 virtual memory (kbytes, -v) unlimited ~iainmcgin$ulimit-a 核心文件大小(块,-c)0 数据段大小(千字节,-d)不受限制 文件大小(块,-f)不受限制 最大锁定内存(KB,-l)不受限制 最大内存大小(千字节,-m)不受限制 打开文件(-n)256 管道大小(512字节,-p)1 堆栈大小(千字节,-s)8192 cpu时间(秒,-t)不受限制 最大用户进程(-u)266 虚拟内存(KB,-v)不受限制 从我上面的设置来看,似乎每个进程的内存使用没有限制。出于某种原因,你的同事可能不是这样

    我用的是雪豹:

    ~ iainmcgin$ uname -rs Darwin 10.6.0 ~iainmcgin$uname-rs 达尔文10.6.0
    答案在于执行这项计划


    从OS X 10.6开始,将为64位平台上的垃圾收集内存分配一个8GB的竞技场。该竞技场因分配量大(>=128k)和分配量小而被削减一半(您是否以64位模式运行操作系统?可以运行64位进程,但我认为除非操作系统也以64位模式运行,否则您无法获得64位的全部好处。我认为这可能会对您的情况产生影响。正如我在问题中试图澄清的那样,我正在使用缓冲区来解压缩图像,因此映射文件不是一个选项。关于ur声明:“如果长度超过可用内存,您将得到零。”:这正是问题所在。我对虚拟内存(与交换空间一起)的理解是,只要地址空间没有填满,分配就不会失败。非常正确,对此表示抱歉。在我的(有限的)中测试
    NSData
    在64位进程中分配大量GB内存从来没有遇到过问题。它在32位机器中的内存限制为2GB。无论如何,因为NSData是一个对象,它必须存在于Objective-C运行时中,该运行时分配堆上的所有对象。对于非常大的分配,您可能需要使用
    CFData
    函数,因为它们不会产生这样的开销,并且允许您使用Mach的Copy-On-Write内存管理。您还可以检查他的系统日志,查看分配失败是否记录了应该记录的异常。Th