【问题标题】:what is the maximum size of dynamic memory that could be allocated by using C++ in windows?在 Windows 中使用 C++ 可以分配的动态内存的最大大小是多少?
【发布时间】:2018-08-26 16:35:20
【问题描述】:
#include<iostream>
#include<chrono>
using namespace std;
using namespace std::chrono;

class rmq
{
public:
    rmq() = default;
    rmq(size_t size) :m_pData(new unsigned int[size]), m_size(size) {}
    ~rmq(){   if (m_pData)delete[]m_pData;}
    void populateValue() {
        if (m_pData) {
            for (size_t i = 0; i < m_size; i++) m_pData[i] = i;
        }
        else {
            std::cout << "NUll reference" << std::endl;
        }
    }
    unsigned int minQuery(size_t firstIdx, size_t lastIdx) {
        unsigned int minValue = 0;
        if (firstIdx < lastIdx && lastIdx <= m_size) {
            minValue = m_pData[firstIdx];
            while (++firstIdx < lastIdx) {
                if (minValue > m_pData[firstIdx]) minValue = m_pData[firstIdx];
            }            
        }
        return minValue;
    }
private:
    unsigned int *m_pData;
    size_t m_size;
};
int main()
{
    rmq r(UINT32_MAX);
    r.populateValue();

    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    int minvalue = r.minQuery(0, UINT32_MAX);
    high_resolution_clock::time_point t2 = high_resolution_clock::now();

    auto duration = duration_cast<nanoseconds>(t2 - t1).count();
    std::cout << "RMQ:" << minvalue <<" "<<"Duration_i`enter code here`n_ns:"<<duration<<std::endl;    

    return 0;
}

当大小指定为 UINT32_MAX 时,我得到以下异常

RMQ.exe 中 0x763BC54F 处未处理的异常:Microsoft C++ 异常:内存位置 0x004CFAC0 处的 std::bad_array_new_length。

但同样的事情也适用于 UINT16_MAX。无法理解其背后的逻辑。

编译器版本为 Visual C++ 2015(也称为 Visual C++ 14.0)。

目标架构:x86

【问题讨论】:

  • 可用内存的最大大小取决于:您是否编译为 x64,以及您机器上的可用 RAM。
  • 请给我们一个minimal reproducible example 吗?我们无需查看您的 rmq 课程即可重现该问题。
  • 你知道UINT16_MAX65535,而UINT32_MAX 是四十亿多一点?它们之间有很大的不同。
  • @AlgirdasPreidžius:可用地址空间几乎不取决于 RAM 的数量。您应该将 RAM 视为一种性能优化。
  • @IInspectable 是的,我忘记了虚拟内存(又名交换)是一个东西。但是,在最常见的用例中:内存量 = 软件可用的工作内存量。

标签: c++ windows pointers memory


【解决方案1】:

您正在尝试分配一个包含 2^32 个元素的整数数组。这需要 16 GiB 的内存。

在 32 位地址空间中,最大可用内存总量为 4GiB。在 Windows 中,您最多可以分配给 32 位进程的是 32 位窗口中的 3GiB 或 64 位窗口中的 4GiB。对于 64 位进程,这上升到 8TiB+。

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx

请注意,如果您的总可用 RAM 和交换空间不够大,即使您低于这些限制,分配仍可能失败。

【讨论】:

  • 请注意,有问题的异常是在任何尝试分配内存之前引发的。核心问题不在于内存资源不足。相反,它是由于遇到数据类型约束,未能保持足够大的字节数来表示请求的存储大小而引起的。虽然此答案中的内容没有错,但它也没有解决所提出的问题。
【解决方案2】:

std::bad_array_new_length 异常会在以下情况之一引发:

  1. 数组长度为负数
  2. 新数组的总大小将超过实现定义的最大值
  3. 初始化子句的数量超过了要初始化的元素数量

您的代码在尝试执行表达式new unsigned int[UINT32_MAX] 时遇到了第二个要点。这会尝试分配具有 2^32 - 1 个元素的 unsigned ints 数组。 Visual Studio 中 unsigned int 的大小为 4,因此数组的总大小(以字节为单位)为 4 * (2^32 - 1)。该大小无法使用std::size_t 表示,因此无法传递给std::malloc(在Visual Studio 的实现中operator new 最终会调用它),因此实现会出现异常。

如果您需要分配一个 2^32 - 1 unsigned ints 的数组,则必须针对 64 位目标进行编译。 unsigned ints 的最大数组是 unsigned int[UINT32_MAX &gt;&gt; 2],您可以请求 32 位目标而不获取 std::bad_array_new_length。请注意,这仍然会给您一个std::bad_alloc 异常。

分配unsigned ints 和UINT16_MAX 元素的数组相当于4 * (2^16 - 1) 字节,大约256kB。分配的内存量并不完全是惊人的,因此(通常)会毫无例外地处理请求。

【讨论】:

  • 感谢您的准确回答。我尝试使用 x64 并发现它可以正常工作。并且理解其背后的逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-29
  • 2019-05-12
  • 1970-01-01
  • 2011-06-29
  • 1970-01-01
  • 2011-07-31
  • 2011-09-26
相关资源
最近更新 更多