我正在 64GB Mac Studio 上工作,但也尝试了 Linux 下的代码。所有均为截至 2023 年 11 月的最新版本,macos 上为 clang 15.0.0。 Linux 上的 gcc 12.3.0。
ulimit
告诉我,除了堆栈大小、进程和文件描述符之外,我们是不受限制的。)
我在 C 中处理very大型数组时遇到麻烦,声明为
static
以避免堆栈。在Macos上,我什至无法分配1GB。在 Linux 上,我不能超过 11GB。 (是的,我确实有这么大的数据集。考虑到台式计算机现在可以有 256GB 或更多,我本以为 C 基础将被设置为默认处理这么多 RAM。)
可以可靠地生成此错误(减少)的基本代码如下。现在人们如何处理这个问题?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define SSS 2025L // at 2025, this dies on macos
#define MB (1024*1024L)
#define DIM (SSS*MB)
static uint8_t storagearray[DIM];
int main(int argc, char *argv[]) {
memset( storagearray, 1, sizeof storagearray );
fprintf(stderr, "[clear ok on %ld = %ld B = %ld MB]\n",
DIM, sizeof(storagearray), sizeof(storagearray)/1024/1024);
long int sum=0;
for (long ix=0; ix < DIM; ++ix) sum+= storagearray[ix];
fprintf(stderr, "[write ok %ld, exit]\n", sum);
return 0;
}
当 SSS 为 2025L 或更高时,它会因以下两个错误之一而使 maos 不及格:
总线错误(或使用 -fsanitize=address,违规)
调用时(不是运行一段时间后)
dyld[99042]: dyld cache '(null)' not loaded: syscall to map cache into shared region failed
dyld[99042]: Library not loaded: /usr/lib/libSystem.B.dylib
Referenced from: <BB88C06F-4A2F-3CCB-8270-8A6D2E5DC717> /Users/ivo/Sync/research/country-climate-data-gridded/econ-activity/nightlites/data/a.out
Reason: tried: '/usr/lib/libSystem.B.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/lib/libSystem.B.dylib' (no such file), '/usr/lib/libSystem.B.dylib' (no such file, no dyld cache)
当SSS为12,000时,它会显示“已杀”。当它达到 15,000 时,它会显示“segfault”。
告诉我我们是无限的,除了 堆栈大小、进程和文件描述符。)ulimit
“无限”不应按字面意思理解。这意味着操作系统不会对给定的资源类型施加任何“额外”限制,但操作系统和 C 实现中仍然存在内置限制,最终您会受到机器硬件的限制。
我在 C 中处理非常大的数组时遇到麻烦,将其声明为静态 避免堆栈。在文件范围声明数组足以为其提供静态存储持续时间。另外声明它
static
不会对它的存储位置产生进一步的影响,至少就 C 语言而言是这样。 (在函数内部声明的变量则不然。)
在macOS上,我什至无法分配1GB。在Linux上,我 不能超过11GB。这是操作系统和 C 实现的函数。没有什么要求您的 C 实现能够支持任意大的声明对象。
现在人们如何处理这个问题?
这又是操作系统和 C 实现的一个功能,但通常您可以动态分配比静态或(尤其是)自动分配的对象更大的对象。如果您无法静态分配足够大的对象,那么动态分配(
malloc
或
calloc
)是您最好的选择。