【问题标题】:C++ Program Crashes Due To Large Array Even Though It's On The HeapC++ 程序由于大数组而崩溃,即使它在堆上
【发布时间】:2013-01-22 13:43:14
【问题描述】:

我正在为三个非常大的数组 (N = 990000001) 分配内存。我知道你必须在堆上分配它,因为它太大了,但即使我这样做,程序也会不断崩溃。是我分配不正确还是我的计算机根本没有足够的内存(我应该有足够的内存)?可能是问题的另一件事是我以某种方式错误地分配了我的内存。当 N 很小时,我现在分配内存的方式工作得很好。任何帮助表示赞赏。

int main()
{
double *Ue = new double[N];
double *U = new double[N];
double *X = new double[N];
for (int i = 0; i < N; i++)
{
    X[i] = X0 + dx*i;
    Ue[i] = U0/pow((X0*X[i]),alpha);
}

//Declare Variables
double K1;double K2; double K3; double K4;

//Set Initial Condition
U[0] = U0;
for (int i = 0; i < N-1; i++)
{
    K1 = deriv(U[i],X[i]);
    K2 = deriv(U[i]+0.5*dx*K1,X[i]+0.5*dx);
    K3 = deriv(U[i]+0.5*dx*K2,X[i]+0.5*dx);
    K4 = deriv(U[i]+dx*K3,X[i+1]);
    U[i+1] = U[i] + dx/6*(K1 + 2*K2 + 2*K3 + K4);
}

return 0;
}

【问题讨论】:

  • 程序如何崩溃?如果你不告诉我们原因......
  • 澄清:990000001 == 990,000,001
  • 8 bytes * 3 * 990000001 = 22.13GB。很可能它正在抛出std::bad_alloc
  • 至少是在编译吗?
  • 所以一个double一般使用8个字节,而你每个数组有9.9亿个double?一台标准的 PC 电脑不可能有超过 22GB 的内存。

标签: c++ arrays memory-management crash heap-memory


【解决方案1】:

您的程序分配并使用了大约 24 GB 的内存。

如果你是一个 32 位进程的程序,这将抛出std::bad_alloc,并且你的程序将正常退出。 (理论上你的工具链中可能存在溢出错误,但我认为这不太可能。)

如果您是 64 位进程的程序,您可能会被 OOM 杀手卡住,您的程序将不正常地退出。除非您有 24 GB 的 RAM + 交换组合,否则您可能会以磁盘的速度运行。 (如果您实际上有 24 GB 的 RAM,那么它可能不会崩溃,因此我们可以排除这种情况。)如果禁用过度使用,那么您将获得 std::bad_alloc 而不是 OOM 杀手。 (这一段是特定于 Linux 的,尽管其他内核类似。)

解决方案:使用更少的内存或购买更多的 RAM。

【讨论】:

  • 我有 16 GB 的 RAM,但我假设计算机将开始使用磁盘上的交换内存并完成工作(尽管速度较慢)。我的假设很糟糕。
  • 据我所知,它的 4GB 用于 32 位操作系统中的程序。但如果您的操作系统是 64 位,那么这应该是 RAM 或 SWAP 空间的问题。在后一种情况下尝试增加 SWAP。
  • @user1562781:这取决于你的机器是如何配置的。我不知道Windows内存系统的细节。在 Linux 上,运行 /sbin/swapon -scat /proc/swaps 以查看交换分区列表。我认为这些给出了以 512 字节为单位测量的大小,因此大小应该远高于 1600 万才能让您的程序运行(因为 1600 万 * 512B + 16 GB = 24 GB)。
【解决方案2】:

如果在 Windows 上,您可能会发现此信息很有用 Memory Limits for Applications on Windows -

请注意,静态数据和堆栈数据的限制在两者中是相同的 32 位和 64 位变体。这是由于 Windows 的格式 可移植可执行 (PE) 文件类型,用于描述 EXE 和 链接器布局的 DLL。它具有用于图像部分的 32 位字段 偏移量和长度,并且未针对 64 位变体进行扩展 视窗。与在 32 位 Windows 上一样,静态数据和堆栈共享相同的 前 2GB 的地址空间。

那么,唯一真正的改进——

动态数据 - 这是在程序期间分配的内存 执行。在 C 或 C++ 中,这通常使用 mallocnew 完成。

64 位

  • 静态数据 2Gb

  • 动态数据 8Tb

  • 堆栈数据 1GB (栈大小由链接器设置,默认为1MB。这个可以 使用链接器属性 System > Stack Reserve Size 增加)

单个数组的分配“应该能够分配到操作系统愿意处理的大小”(即受 RAM 和碎片限制)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-29
    • 2011-02-05
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    相关资源
    最近更新 更多