[ODE] Stack overflow

Marco Grubert mgrubert at conitec.net
Mon Feb 3 14:22:02 2003


As promised- here is the code I am using to prevent Stack overflows from
breaking the app, sorry for lack of formatting. I am still looking for an
answer on how Windows manages virtual memory, i.e. what effect setting the
/STACK size has.


////////////////////////////////////////////////////////////////////////////
/////////////////////////////
// check what type of exception and let win32 know whether we want to handle
it
int __stdcall FilterException(DWORD dwException)
{
return (dwException==STATUS_STACK_OVERFLOW) ? EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH;
}

////////////////////////////////////////////////////////////////////////////
/////////////////////////////
// call to dWorldStep wrapped in an exception handler with Stack-rebuild
(from Dr.GUI)
unsigned __stdcall StepWorldThread(void* pvParam)
{
// worldstep has a tendency to blow the default 1MB Stack
// so create an excpetion-safe thread with its own stack space
__try {
  float* pdT= static_cast<float*> (pvParam);
  // move forward
  dWorldStep( pMyWorld, *pdT );
} __except(FilterException( GetExceptionCode() )) {
// stack overflow- restore old state, inform user
LPBYTE lpPage;
static SYSTEM_INFO si;
static MEMORY_BASIC_INFORMATION mi;
static DWORD dwOldProtect;
// We do this to get the page size of the system
GetSystemInfo(&si);
// We want the address that the stack pointer is // pointing to
_asm mov lpPage, esp;
// We wanna learn the allocation base of the stack
VirtualQuery(lpPage, &mi, sizeof(mi));
// go to the page below the current page.
lpPage = (LPBYTE) (mi.BaseAddress) - si.dwPageSize;
// Free the portion of the stack that you just abandoned
// If it looks like you are freeing the portion
//of the stack that you still need,
// Remember that stacks grow down.
if (!VirtualFree(mi.AllocationBase,
(LPBYTE)lpPage - (LPBYTE) mi.AllocationBase,
MEM_DECOMMIT))
{
// notify main thread that we're done (serious problem=-1)
_endthreadex( -1 );
}
// Reintroduce the guard page
if (!VirtualProtect(lpPage, si.dwPageSize,
PAGE_GUARD | PAGE_READWRITE, &dwOldProtect))
{
// notify main thread that we're done (serious problem=-1)
_endthreadex( -1 );
}
// notify main thread that we're done (failure=0)
_endthreadex( 0 );
return 0;
}
// notify main thread that we're done (successful=1)
_endthreadex( 1 );
return 0;
}

////////////////////////////////////////////////////////////////////////////
/////////////////////////////
// Call this function for stepping instead of dWorldStep
// returns TRUE if things worked okay, or FALSE if error occured
bool StepWorld (float dT)
{
// worldstep has a tendency to blow the stack
// so create an excpetion-safe thread with its own stack space
unsigned dwThreadID, dwResult;
HANDLE hThread= reinterpret_cast<HANDLE>( _beginthreadex(
0,0, StepWorldThread, static_cast<void*>(&dT), 0, &dwThreadID) );
if (hThread!=0)
{
// successfully created thread? then wait til its done
WaitForSingleObject( hThread, INFINITE );
// get return value- 0 for error, 1 for okay
GetExitCodeThread( hThread, reinterpret_cast<DWORD*> (&dwResult));
CloseHandle( hThread ); // dispose of thread
}
// check for overflow
if (dwResult!=1 || hThread==0)
{
// worldstep wrecked havoc - now what?
return false;
} else {
return true;
}
}