C++中是否存在最大数组长度限制?

lui*_*iss 163 c++ arrays

C++中的数组是否有最大长度?

它是C++限制还是取决于我的机器?它可以调整吗?它取决于数组的类型吗?

我可以以某种方式突破该限制,还是必须寻找更好的信息存储方式?什么应该是最简单的方法?

我要做的是在数组上存储long long int,我在Linux环境中工作.我的问题是:如果我需要存储N> 10位数的N长整数数组,我该怎么办?

我需要这个,因为我正在为学校编写一些加密算法(例如p-Pollard),然后点击这个整数墙和数组表示的长度.

Kon*_*lph 156

有两个限制,既不是由C++强制执行,而是由硬件强制执行.

第一个限制(永远不应该达到)由用于描述数组中索引的大小类型的限制(及其大小)设置.它由系统std::size_t可以采用的最大值给出.此数据类型应始终是系统的最大整数类型.

另一个限制是物理内存限制.数组中的对象越大,达到此限制的时间越早,因为内存已满.例如,vector<int>给定大小n的a通常占用类型数组的大约四倍的内存vector<char>(减去一个小的常数值).因此,a vector<char>可能包含比vector<int>内存已满之前更多的项目.对于本机C风格的数组int[]char[].

另外,这个上限可能受到allocator用于构造它的类型的影响,vector因为allocator可以以任何方式自由地管理存储器.一个非常奇怪但仍然可以想象的分配器可以以一种对象的相同实例共享资源的方式来池化内存.这样,您可以将大量相同的对象插入到容器中,否则会耗尽所有可用内存.

除此之外,C++不强制执行任何限制.

  • 此外,您通常可以轻松地达到堆栈大小限制,尤其是在使用又是特定于实现(但能够更改)的线程时. (17认同)
  • std :: size_t通常(总是?)指针的大小,而不是整数数学单元中具有本机硬件支持的最大整数的大小.在我使用的每个x86操作系统上,对于32位操作系统,size_t为32位,对于64位操作系统,size_t为64位. (10认同)
  • 我的理解是*array*的最大限制是处理器*word*的最大值.这是由索引操作符引起的.例如,机器可以具有16位的字大小,但是具有32位的寻址寄存器.通过传递给`new`或`malloc`的参数,大小的内存大小有限.可以通过指针访问大于数组的大块内存. (2认同)

Mar*_*ork 156

没有人提到堆栈框架大小的限制.

有两个地方可以分配内存:

  • 在堆上(动态分配的内存).
    这里的大小限制为可用的硬件组合和OS的使用其他设备暂时存放未使用的数据(模拟空间能力,移动页面到硬盘).
  • 在堆栈上(本地声明的变量).
    这里的大小限制是编译器定义的(具有可能的硬件限制).如果您阅读编译器文档,您通常可以调整此大小.

因此,如果您动态分配一个数组(限制很大,并由其他帖子详细描述.

int* a1 = new int[SIZE];  // SIZE limited only by OS/Hardware
Run Code Online (Sandbox Code Playgroud)

或者,如果数组在堆栈上分配,那么您将受到堆栈帧大小的限制.NB向量和其他容器在堆栈中的存在很少,但通常大部分数据都在堆上.

int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame
Run Code Online (Sandbox Code Playgroud)

  • 大数组的首选分配不在堆栈上或全局定义,而是通过动态分配(通过`new`或`malloc`). (4认同)
  • @Thomas Matthews:不在我的世界里。动态分配的对象需要管理。如果需要动态分配,我将使用一个代表动态分配内存的堆栈对象,如 std::vector。 (2认同)
  • 有一个缺失的cornor案例:`Global Arrays`,虽然不是美,最好避免,但这些不属于`stack`的限制,你不需要`malloc` /`free`与它们一起工作. (2认同)
  • 非常重要的一点.我最近遇到了一个"生产质量"的开源项目,该项目提供了可配置的最大缓冲区大小.所有缓冲区都在堆栈上分配,因此配置足够大的值会导致程序在启动时立即发生段错误. (2认同)

Sma*_*acL 13

从实用而非理论的角度来看,在32位Windows系统上,单个进程可用的最大内存总量为2 GB.您可以通过使用具有更多物理内存的64位操作系统来突破限制,但是,是否执行此操作或查找替代方案在很大程度上取决于您的预期用户及其预算.您也可以使用PAE进行一些扩展.

数组的类型非常重要,因为许多编译器的默认结构对齐是8个字节,如果内存使用是一个问题,这是非常浪费的.如果您使用Visual C++来定位Windows,请查看#pragma pack指令作为克服此问题的方法.

另一件事是看内存压缩技术可能对你有什么帮助,例如稀疏矩阵,即时压缩等等......再次,这是高度依赖于应用程序的.如果您编辑帖子以提供有关阵列中实际内容的更多信息,您可能会获得更多有用的答案.

编辑:给出关于您的确切要求的更多信息,您的存储需求似乎在7.6 GB到76 GB之间未压缩,这需要相当昂贵的64位盒作为数组存储在C++的内存中.它提出了一个问题,为什么要将数据存储在内存中,其中假设访问速度,并允许随机访问.将此数据存储在数组之外的最佳方法几乎取决于您希望如何访问它.如果您需要随机访问数组成员,对于大多数应用程序,往往会有一些方法可以对可能同时访问的数据块进行分组.例如,在大型GIS和空间数据库中,数据通常按地理区域进行平铺.在C++编程术语中,您可以覆盖[]数组运算符,以根据需要从外部存储中获取部分数据.


kay*_*eck 6

与当前所有答案一样令人讨厌的非特定性,它们大多是正确的,但有许多警告,并不总是被提及。要点是,你有两个上限,其中只有一个是实际定义的,所以YMMV

1. 编译时间限制

基本上,您的编译器将允许的内容。对于 x64 Windows 10 机器上的 Visual C++ 2017,这是我在编译时达到 2GB 限制之前的最大限制,

unsigned __int64 max_ints[255999996]{0};
Run Code Online (Sandbox Code Playgroud)

如果我这样做,

unsigned __int64 max_ints[255999997]{0};
Run Code Online (Sandbox Code Playgroud)

我会得到:

Error C1126 automatic allocation exceeds 2G

我不确定 2G 与255999996/ 的关系7。我GOOGLE了两个号码,我能找到的唯一的事情这是可能相关的是这样的* nix的Q&A关于精度问题dc。无论哪种方式,您尝试填充哪种类型的 int 数组似乎都不重要,重要的是可以分配多少元素。

2. 运行时间限制

您的堆栈和堆有其自身的局限性。这些限制都是根据可用系统资源以及您的应用程序本身的“重”程度而变化的值。例如,使用我当前的系统资源,我可以让它运行:

int main()
{
    int max_ints[257400]{ 0 };
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是如果我稍微调整一下......

int main()
{
    int max_ints[257500]{ 0 };
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

砰!堆栈溢出!

Exception thrown at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000). Unhandled exception at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000).

只是为了详细说明您的应用程序点的整体重量,这很好:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[400]{ 0 };
    return 0;
}  
Run Code Online (Sandbox Code Playgroud)

但这导致了堆栈溢出:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[500]{ 0 };
    return 0;
}  
Run Code Online (Sandbox Code Playgroud)