Here's another proof that Windows does overcommit stacks:
#include <Windows.h>
#include <iostream>
#include <sstream>
#pragma warning(disable: 6387) // parameter ... could ne null
using namespace std;
int main( int argc, char **argv )
{
auto stackThread = []( LPVOID lpvThreadParam ) -> DWORD
{
char const *stackTop, *stackBottom;
GetCurrentThreadStackLimits( &(ULONG_PTR &)stackBottom, &(ULONG_PTR
&)stackTop );
SYSTEM_INFO si;
GetSystemInfo( &si );
MEMORY_BASIC_INFORMATION mbi;
auto query = [&]( char const *p ) -> char const *
{
if( VirtualQuery( p, &mbi, sizeof mbi ) != sizeof mbi )
ExitProcess( EXIT_FAILURE );
return (char *)mbi.AllocationBase;
};
char const *base = query( stackBottom ), *p;
do
{
cout << mbi.RegionSize / si.dwPageSize << ": ";
unsigned n = 0;
auto append = [&]<typename ... T>( T &&... values ) { if( n++ ) cout
<< ", "; ((cout << values), ...); };
if( mbi.State != MEM_FREE )
if( mbi.State == MEM_COMMIT )
append( "comitted" );
else if( mbi.State == MEM_RESERVE )
append( "reserved" );
else
append( "S: 0x", hex, mbi.State );
if( !mbi.Protect )
append( "unacessible" );
else if( mbi.Protect & PAGE_GUARD )
append( "guard page" );
else if( mbi.Protect == PAGE_READWRITE )
append( "read-write" );
else
append( "P: 0x", hex, mbi.Protect );
cout << endl;
p = (char *)mbi.BaseAddress + mbi.RegionSize;
} while( query( p ) == base );
return 123;
};
HANDLE hThread = CreateThread( nullptr, 0x100000, stackThread, (void
*)(ptrdiff_t)(argc >= 2), STACK_SIZE_PARAM_IS_A_RESERVATION, nullptr);
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
return 0;
}
This prints the attributes of the pages in the range of the stack.