Discussion:
I have HEAP big trouble
(too old to reply)
Alan Williams-Key
2009-10-15 16:22:55 UTC
Permalink
(Sorry if this is not the right newsgroup - couldn't find a more appropriate
one).
I'm trying to find a problem in my program and I suspected a problem with
the heap - maybe leaky code. So I was looking at the heap usage with a small
function I found on the internet somehwere. Only trouble is that it entered
an infinite loop. I think this might point to a problem but I don't know what
it is. Here's the code with an additional fix to catch the inifinite loop:

int CountWalk()
{
int HeapStatus;
int lastPentry = 0;
BOOL running = TRUE;
_HEAPINFO info;
info._pentry = NULL;
int UsedBytes = 0;

while(running)
{ /* scan heap */
HeapStatus = _heapwalk(&info);
switch(HeapStatus)
{ /* check status */
case _HEAPOK:
break;
case _HEAPEND:
running = FALSE;
break;
default:
ASSERT(FALSE);
running = FALSE;
continue;
} /* check status */

if(info._useflag == _USEDENTRY)
{ /* used block */
UsedBytes += info._size;
} /* used block */

// extra termination required to avoid infinite loop !!!
if ((int)info._pentry == lastPentry)
running = FALSE;
else
lastPentry = (int)info._pentry;
} /* scan heap */
return UsedBytes;
} // CMemStatsDlg::CountWalk

What was happening was that _heapwalk() was returning the same unused heap
block. I know this because the _pentry data didn't change. The status return
was _HEAPOK.

Anyone got any idea what sort of error could put the heap into a state where
_heapwalk() could malfunction this way?

Alan
(VS6 C++)
Ben Voigt [C++ MVP]
2009-10-16 01:23:52 UTC
Permalink
Post by Alan Williams-Key
(Sorry if this is not the right newsgroup - couldn't find a more appropriate
one).
I'm trying to find a problem in my program and I suspected a problem with
the heap - maybe leaky code. So I was looking at the heap usage with a small
function I found on the internet somehwere. Only trouble is that it entered
an infinite loop. I think this might point to a problem but I don't know what
int CountWalk()
{
int HeapStatus;
int lastPentry = 0;
BOOL running = TRUE;
_HEAPINFO info;
info._pentry = NULL;
int UsedBytes = 0;
while(running)
{ /* scan heap */
HeapStatus = _heapwalk(&info);
switch(HeapStatus)
{ /* check status */
break;
running = FALSE;
break;
ASSERT(FALSE);
running = FALSE;
continue;
} /* check status */
if(info._useflag == _USEDENTRY)
{ /* used block */
UsedBytes += info._size;
} /* used block */
// extra termination required to avoid infinite loop !!!
if ((int)info._pentry == lastPentry)
running = FALSE;
else
lastPentry = (int)info._pentry;
} /* scan heap */
return UsedBytes;
} // CMemStatsDlg::CountWalk
What was happening was that _heapwalk() was returning the same unused heap
block. I know this because the _pentry data didn't change. The status return
was _HEAPOK.
Anyone got any idea what sort of error could put the heap into a state where
_heapwalk() could malfunction this way?
Writing over the heap header (which is usually placed right before the data
block that malloc or new give to you).
Post by Alan Williams-Key
Alan
(VS6 C++)
__________ Information from ESET NOD32 Antivirus, version of virus
signature database 4512 (20091015) __________
The message was checked by ESET NOD32 Antivirus.
http://www.eset.com
__________ Information from ESET NOD32 Antivirus, version of virus signature database 4512 (20091015) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com
Alan Williams-Key
2009-10-17 08:46:01 UTC
Permalink
Post by Ben Voigt [C++ MVP]
Writing over the heap header (which is usually placed right before the data
block that malloc or new give to you).
Thanks. Initially I thought this would allow me to find the problem but upon
further testing I discovered the heap is already in this state at the start
of InitInstance()! Now as it happens I am using some code I found over at the
Code Project for attaching my own exception handler, so I can check the heap
through the whole of the initialization process (sorry the next code extract
is long):

int AFXAPI AfxWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// Wrap WinMain in a structured exception handler (different from C++
// exception handling) in order to make sure that all access violations
// and other exceptions are displayed - regardless of when they happen.
// This should be done for each thread, if at all possible, so that
exceptions
// will be reliably caught, even inside the debugger.
__try
{
//point 1
TRACE(_T("in ExceptionAttacher.cpp - AfxWinMain\n"));

// The code inside the __try block is the MFC version of AfxWinMain(),
// copied verbatim from the MFC source code.
ASSERT(hPrevInstance == NULL);

int nReturnCode = -1;
CWinApp* pApp = AfxGetApp();

// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// point 2
// App global initializations (rare)
ASSERT_VALID(pApp);
if (!pApp->InitApplication())
goto InitFailure;

// point 3

ASSERT_VALID(pApp);
res = heapOK();

// Perform specific initializations
if (!pApp->InitInstance())
{
if (pApp->m_pMainWnd != NULL)
{
TRACE(_T("Warning: Destroying non-NULL m_pMainWnd\n"));
pApp->m_pMainWnd->DestroyWindow();
}
nReturnCode = pApp->ExitInstance();
goto InitFailure;
}
ASSERT_VALID(pApp);

nReturnCode = pApp->Run();
ASSERT_VALID(pApp);

InitFailure:
#ifdef _DEBUG
// Check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
{
TRACE(_T("Warning: Temp map lock count non-zero (%ld).\n"),
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif

AfxWinTerm();
return nReturnCode;
}
__except(RecordExceptionInfo(GetExceptionInformation(),
_T("ExceptionAttacher.cpp - AfxWinMain")))
{
// Do nothing here - RecordExceptionInfo() has already done
// everything that is needed. Actually this code won't even
// get called unless you return EXCEPTION_EXECUTE_HANDLER from
// the __except clause.
}
return 0;
}

I've tested the heap at point 1, point 2 and point 3 and it is invalid in
all these places. So where does it get initialized, or is there something
wrong in the logic of my heap walking?

Alan
Alan Williams-Key
2009-10-17 11:00:01 UTC
Permalink
Post by Alan Williams-Key
I've tested the heap at point 1, point 2 and point 3 and it is invalid in
all these places. So where does it get initialized, or is there something
wrong in the logic of my heap walking?
Alan
Well there must be something wrong with my heapwalk. I switched to using
_heapset and found where the heap was getting corrupted. So thank to everyone
for pointing me in the direction of a heap problem though I still can't see
the problem with the heap walk.

Alan

Loading...