16

以下代码不会引发异常并打印“成功”。为什么 ?

#include <iostream>

int main() 
{
    size_t size = size_t(1024)*1024*1024*1024*1024*1024*1024*1024;
    char* data = new char[size];

    if (data == NULL)
        std::cout << "fail" << std::endl;
    else
        std::cout << "success" << std::endl;

    return 0;
}
  • 编译器:g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
  • 操作系统:Ubuntu 12.04
  • 内存:8 GB

如果这是它的工作方式,我如何检查我是否有足够的内存?

[编辑:使我的愚蠢代码更正确,现在如果我删除两个,它至少会在 x64 上失败*1024]

4

5 回答 5

20

我的编译器可以回答这个问题:

$ g++ --version
g++ (GCC) 4.7.1 20120721 (prerelease)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ -Wall -Wextra -pedantic q12507456.c++
q12507456.c++: In function 'int main()':
q12507456.c++:5:42: warning: integer overflow in expression [-Woverflow]
$
于 2012-09-20T07:16:49.837 回答
6

这很可能是因为您请求的数字太大而无法存储在整数中,并且您在这里遇到溢出,并且分配的内存实际上远低于您的想象。

这里 2^80 = 1208925819614629174706176 根据http://en.wikipedia.org/wiki/Yobibyte

于 2012-09-20T07:01:29.707 回答
5
1024*1024*1024*1024*1024*1024*1024*1024

计算时会导致整数溢出 - 也就是说,它将取模 2^32(或 2^64,取决于您的系统),这是可以分配的零字节。

于 2012-09-20T07:02:21.177 回答
4

请注意,在 linux 上malloc(最终支持new)可能会过度使用:

从 2.1.27 开始,有一个 sysctlVM_OVERCOMMIT_MEMORY和 proc 文件 /proc/sys/vm/overcommit_memory ,其值为 1:做 overcommit,0(默认):不做。

malloc将成功并保留 VA,但不会使用页面备份它。当一个页面被访问时,它可能会也可能不会成功提交它。OOM Killer可能会运行。如果一切都失败了,您将获得一个 GPF 访问权限。

这种行为是疯狂的(理智的人在这个阵营)还是聪明的(疯狂的人在那个阵营),意见分歧。

于 2012-09-20T07:23:39.173 回答
1

也许您知道以下内容,但我将说明它只是为了澄清。没有从字面上抛出异常,代码正在通过 if 语句进行测试。无论您在测试中使用什么术语和方法,都需要注意更相关的观察结果。您的系统拥有整数的最大值,C++ 将在编译期间通过检查并采取相应的方式将其考虑在内。再一次,你可能也已经知道了。我的猜测是,该值要么回到 0,然后达到过量,要么在指针开始指向它之前存在的值保持不变(很可能)。在这种情况下,指针不会是NULL. 尝试给予NULL声明后,然后分配内存并查看天气是否通过您的 if 语句。

于 2012-09-20T07:20:50.917 回答