c++ 在内存耗尽之前,我可以声明多少个const变量?

wbgh16ku  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(100)

我写的代码有很多const变量(主要是int和enum),我想知道,我可以声明的变量的最大数量是多少?我的想法是,这些const变量在堆栈上分配,这意味着我可以声明大约1 MB/4 bytes = 250000个变量(这是足够的),假设堆栈大小为1 MB。我是正确的吗?
举个简单的例子来说明我的意思:
Test.cpp:

const unsigned int VECTOR_ID = 4;
const unsigned int MATRIX_ID = 3;

int main()
{
  std::cout << VECTOR_ID << " : " << MATRIX_ID << std::endl;
  return 0;
}

字符串

klsxnrf1

klsxnrf11#

注意,在编译时已知的常量可能不对应于任何对象;当你在编译时启用了优化,常量将直接编译到机器指令中作为 * 立即值。* Here是一个简单的例子。这意味着常量变量的数量没有限制。这也意味着根本不使用的常量可能会完全消失。(如果它们以任何非平凡的方式使用,代码的大小将超过数据的大小。
即使你的常量变量确实变成了对象,例如,因为它们的地址被取了,它们也会被“编译到你的程序中”,成为可执行文件的一部分。
程序的大小及其段的大小受可执行文件的格式、系统资源以及潜在的构建工具的限制。Intel page似乎表明,即使在64位体系结构上(仍然比您的用例大三个数量级),静态数据(全局常量可能结束)在Windows下也被限制在2 GB以内:
请注意,在32位和64位变体中,对静态和堆栈数据的限制是相同的。这是由于Windows可移植可执行(PE)文件类型的格式,该文件类型用于描述链接器布局的EXE和DLL。它具有用于图像节偏移量和长度的32位字段,并且未针对Windows的64位变体进行扩展。与32位Windows一样,静态数据和堆栈共享相同的前2GB地址空间。
快速搜索似乎表明,现代Linux中不存在这种限制。
独立于任何二进制限制,构建工具(编译器和链接器)可能有更严格的限制。即使稍后的优化器阶段消除了所有常量,它们的定义仍然需要解析。可能对作用域或翻译单元中的名称数量有限制。

  • 例如,Microsoft C++ has a limit of 6144的成员初始值设定项的数量。
  • The C standard specifies a minimum of 511标识符,但大多数编译器将允许更多。
    *C++20标准(公开草案here,数字相同)规定了附录B中若干数量的 * 建议 * 最小值。其中包括
  • 65 536个外部标识符在一个翻译单元中
  • 在一个块中声明了1024个具有块范围的标识符
  • 一个类中有16 384个非静态数据成员(包括继承的成员)
  • 类的1024个静态数据成员
  • 单个枚举中有4096个枚举常量。

我刚刚创建了一个关于一个C++程序的数据点,这个程序有200万个外部变量和200万个局部变量:

***gcc:**使用x86_64-pc-msys gcc 13.2成功编译。不过,我必须通过在命令行上传递-Wl,--stack,20000000来显式设置堆栈大小(所以它变成了gcc -O0 -Wl,--stack,20000000 -o many2 many2.cpp; 20000000是一个安全的猜测)。如果没有该设置,则会生成可执行文件,但会在运行时崩溃。源代码长101,555,599字节,可执行文件只有64,028字节,280字节。在我的普通电脑上编译需要一分钟多一点的时间。
***MSCV:**cl.exe已经在8% CPU(半个核心)下运行了几个小时。命令行是cl /O0 many2.cpp

自我提示:不要指定-Wall,因为每个未使用的变量都会在终端上生成一个警告。在msys下打印数百万行的mintty文件所花费的时间比我愿意等待的时间要长(外推,这必须是几个小时)。

相关问题