【问题标题】:Why am I getting "Invalid Allocation Size: 4294967295 Bytes" instead of an std::bad_alloc exception?为什么我得到“无效的分配大小:4294967295 字节”而不是 std::bad_alloc 异常?
【发布时间】:2014-06-21 14:37:03
【问题描述】:

我编写了以下代码来为数组分配内存:

try {
    int n = 0;
    cin >> n;
    double *temp = new double[n];
    ...
}
catch(exception& e) {
    cout << "Standard exception: " << e.what() << endl;
    exit(1);
}

当然,我正在检查 n 是否有负值等,但是当我输入一些超过 536*(10^6) 的大数字时,我没有得到一个 bad-alloc 异常,而是一个“无效的分配大小:4294967295 字节”崩溃。

例如我输入 n = 536*(10^6) --> bad-alloc 异常 我输入 n = 537*(10^6) --> Invalid Allocation Size: 4294967295 Bytes --> 崩溃

任何想法为什么会发生这种情况?

【问题讨论】:

  • 您确定要分配 4GB 吗?
  • 在 32 位或 64 位进程上运行?
  • 我并不总是想分配那么多内存,但我不希望我的程序在尝试时崩溃……处理器是 Intel E8400,配备 4GB RAM 和 Win7 64 位。我看到我没有足够的内存,但我不明白为什么它没有给我一个 bad-alloc 异常。
  • 我认为 @MatthiasB 和 @Lightness Races in Orbit 试图告诉你的是,你可能试图分配更多的内存,要么超过系统拥有的内存,要么超过 OS/CPU 的内存支持。
  • 您确定是 536*(10^6) 而不是 536*(10^7)?您可以在cin&gt;&gt;n 之后致电cout&lt;&lt;n 以确保这一点吗?

标签: c++ arrays memory-management bad-alloc


【解决方案1】:

在 32 位系统上,您的虚拟内存地址空间不能超过 2^31-1 (4294967295) 个字节。

您正在尝试分配536000000*sizeof(double) 字节,这显然不止于此。

【讨论】:

  • 这并不能解释为什么它不抛出bad_alloc,这是当您尝试分配的内存超出可用内存时的例外情况。
  • @Barmar:它抛出“Invalid Allocation Size: 4294967295 Bytes”,考虑到分配大小,这非常有意义。
  • 这很有意义,但这不是您的回答所说的。您的回答说它失败了,因为您试图超出您的虚拟机空间。顺便说一句,我认为“明显”之后的第二句中缺少一个词。
【解决方案2】:

调用new double[n] 调用大小为n * sizeof(double) 的全局operator new 函数。如果operator new 然后发现它不能满足请求,它会抛出一个异常。

但是,这不可能在这里发生:nsizeof(double) 的乘积太大,实际上根本无法调用 operator new,因为您请求的大小不适合size_t。实现在处理这个问题的方式上有所不同,但你的显然中止了程序。

如果你想处理这个问题,你可以在尝试分配之前检查n &lt;= SIZE_MAX / sizeof(double)

【讨论】:

  • 感谢这个完美的答案,现在我明白了为什么它会崩溃而不是抛出异常。
  • 我无法在标准中找到任何相关参考。如果你知道一个,你介意分享一下吗?我也无法重现这种行为,无论数字有多大,我都会得到bad_alloc
  • @jrok 该标准未能在 C++11 之前定义行为,因此允许任何行为 (open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#256)。它在 C++11 (open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#624, open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#805) 中发生了变化,因此应该抛出异常(我在标准中找不到引用),但没有发生的事实足以表明OP 没有使用符合 C++11 的实现。
  • @jrok 啊,一开始看错了,但还是找到了。在 C++11 中,它是 5.3.4p7:“如果该 表达式 的值小于零或分配对象的大小将超过实现定义的限制,或者 [.. .],不会获得存储空间,并且 new-expression 通过抛出与 std::bad_array_new_length (18.6.2.2) 类型的处理程序 (15.3) 匹配的类型的异常而终止。"
【解决方案3】:

如果您使用 Visual Studio 进行构建,您可能需要在链接器设置中启用“大内存分配”。

转到项目属性 -> 链接器 -> 系统 -> 启用大型地址设置为“Yes (/LARGEADDRESSAWARE)

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 2019-10-26
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多