为什么 deque::pushback 在仍有可用内存时分配失败?

Why does deque::pushback fail to allocate when there is still memory available?

我是 运行 64 位 Windows 7,在一台有 16GB RAM 的机器上,但是当我执行以下代码时:

#include <deque>
#include <iostream>

using namespace std;

struct Packet
{
    unsigned char* m_buffer;
    int m_bufferSize;

public:
    Packet() :
        m_buffer(nullptr),
        m_bufferSize(0)
    {

    }

    Packet(const Packet& rhs) :
        m_buffer(new unsigned char[rhs.m_bufferSize]),
        m_bufferSize(rhs.m_bufferSize)
    {
        memcpy(m_buffer, rhs.m_buffer, m_bufferSize);
    }

    Packet(unsigned char* newBuffer, unsigned int bufferSize) :
        m_buffer(new unsigned char[bufferSize]),
        m_bufferSize(bufferSize)
    {
        memcpy(m_buffer, newBuffer, bufferSize);
    }

    ~Packet()
    {
        delete[] m_buffer;
        m_buffer = nullptr;
    }

    unsigned char* Buffer()
    {
        return m_buffer;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    deque<Packet> d;

    const int PacketSize = 1051;
    unsigned char* buf = new unsigned char[PacketSize];
    memset(buf, 0, PacketSize);

    const unsigned long FileSize = 2.5 * 1000 * 1000 * 1000;
    const unsigned long MaxAllocations = FileSize / PacketSize; // Simulate buffering a 2.5GB file

    cout << "Simulating loading " << FileSize << " bytes in " << PacketSize << " byte chunks" << endl;
    cout << "Max deque size: " << d.max_size() << endl;
    cout << "Allocations to attempt: " << MaxAllocations << endl;

    for (int i = 0; i < MaxAllocations; ++i)
    {
        Packet p(buf, PacketSize);
        try
        {
            d.push_back(p);
        }
        catch (...)
        {
            cout << "Failed to allocate after " << i + 1 << " attempts" << endl;
            break;
        }
    }

    return 0;
}

我明白了:

Simulating loading 2500000000 bytes in 1051 byte chunks
          Max deque size: 536870911
  Allocations to attempt: 2378686
Failed to allocate after: 1901555 attempts

Windows 任务管理器提示仍有大量内存可用:

那么为什么会失败?

Win32 环境具有 32 位地址 space 和 2Gb 进程分配硬限制。
为 x64 编译的相同代码 运行 没问题。