Will Microsoft Windows 10 overcommit memory?

Solution 1:

Answering my own question, as no one else has.

It seems to be the case that Windows will NOT overcommit memory. This is actually a big difference compared to Linux.

Windows will allow a program to allocate more (virtual) memory than there is RAM on the machine, but ONLY if there is enough free disk space to be able to back the virtual memory requested by the program by disk if necessary.

Solution 2:

Here, the proof that Windows is overcommitting stacks.

Complile this with MSVC / 64 bit:

#include <Windows.h>
#include <iostream>
#include <cstdint>

using namespace std;

DWORD WINAPI stackThread( LPVOID lpvThreadParam );

#pragma warning(disable: 6387) // parameter ... could ne null

int main()
{
    HANDLE hThread = CreateThread( nullptr, 0, stackThread, nullptr, 0, nullptr );
    WaitForSingleObject( hThread, INFINITE );
    CloseHandle( hThread );
    return 0;
}

char *__fastcall getSp();
char *__fastcall getTlsStackLimit();

DWORD WINAPI stackThread( LPVOID lpvThreadParam )
{
    char          *stackTop,
                  *stackBottom;
    char          *curStack   = getSp();
    char          *tlsSp      = getTlsStackLimit(),
                  *efSp       = nullptr,
                  *ehSp       = nullptr,
                  *tlsSpAfter;
    SYSTEM_INFO    si;
    char volatile *p;
    GetCurrentThreadStackLimits( &(ULONG_PTR &)stackBottom, &(ULONG_PTR &)stackTop );
    GetSystemInfo( &si );
    for( p = stackBottom; ; )
        __try
        {
            *p;
            break;
        }
        __except( efSp = getSp(), EXCEPTION_EXECUTE_HANDLER )
        {
            p    += si.dwPageSize;
            ehSp  = getSp();
        }
    tlsSpAfter = getTlsStackLimit();
    (intptr_t &)p     &= -(intptr_t)si.dwPageSize;
    (intptr_t &)tlsSp &= -(intptr_t)si.dwPageSize;
    (intptr_t &)efSp  &= -(intptr_t)si.dwPageSize;
    (intptr_t &)ehSp  &= -(intptr_t)si.dwPageSize;
    cout << "(base for pages is one)" << endl;
    cout << "guard page hit page:    " << (stackTop - p)          / si.dwPageSize << endl;
    cout << "start of tls page:      " << (stackTop - tlsSp)      / si.dwPageSize << endl;
    cout << "exception-filter page:  " << (stackTop - efSp)       / si.dwPageSize << endl;
    cout << "exception-handler page: " << (stackTop - ehSp)       / si.dwPageSize << endl;
    cout << "tls page after gp hit:  " << (stackTop - tlsSpAfter) / si.dwPageSize << endl;
    return 123;
}

and this with MASM

PUBLIC ?getSp@@YAPEADXZ
PUBLIC ?getTlsStackLimit@@YAPEADXZ

_TEXT SEGMENT
?getSp@@YAPEADXZ PROC
    lea     rax, [rsp + 8]
    ret
?getSp@@YAPEADXZ ENDP
_TEXT ENDS

_TEXT   SEGMENT
?getTlsStackLimit@@YAPEADXZ PROC
    mov     rax, gs:[010h]
    ret 0
?getTlsStackLimit@@YAPEADXZ ENDP
_TEXT   ENDS

END

And link it together as a 64 bitt application. First, the curent stack-pointer is taken. Then, the current stack bottom is taken from the thread-environment-block (GS:[010h]). Then the lowest stack address and the address of the first byte after the stack is taken and the page-size is determined. Then the stack is touched from the bottom up to the guard-page. The guard-page will be hit very nearly to the actual stack-pointer and the stack-bottom which was determined from the thread-envinronment-block. After that is pointer is determined again to test if it has been updated by the kernel when the guard-page has been hit. Then the page-indices (1-based) of the guard-page, of the stack-bottom told by the thread-environment-block, of the SEH filter-function, the SEH-handler and the stack-bottom told by the thread-environment-block after the guard-page has hit are shown.