I have abnormal heap growth from my ATL exe program running on NT4.0 Sp3/VC++5.0/ATL 2.1/VS SP3
after 24 hours of execution the memory usage from PView is:
Working Set 2,632 kb
Heap Usage 23,588kb
When I attach with the vc++ debugger and have the program stop gracefully I don't get any memory leak messages. (Bounds checker found nothing as well)
Is there a way to see what the Heap Usage is for each thread and each dll the process is using?
How can the Heap Usage be greater than the Working Set?
(I can't use heapwalker because the executable is loadded by a com call and heapwalker can't attach to a process that is running)
Well, this is very normal, as the working set only is the representation of the _physical_ memory assigned to the process, everything that does not fit in is swapped out.
>>Is there a way to see what the Heap Usage is for each thread
>>and each dll the process is using?
No. The heap is assigned to the whole process, and all threads and modules use the same allocators to access the heap. But you can keep track where the memory is allocated by setting an allocation hook, e.g.
_CrtSetDbgFlag ( _CRTDBG_LEAK_CHECK_DF
| _CRTDBG_DELAY_FREE_MEM_DF
| _CrtSetDbgFlag ( _CRTDBG_REPORT_FLAG)
);
g_pPrevMemHook = _CrtSetAllocHook ( ( _CRT_ALLOC_HOOK) DbgAllocHook);
static char *g_apszMemOperation[] = { "", "allocating", "re-allocating", "freeing" };
static char *g_apszMemBlockType[] = { "Free", "Normal", "CRT", "Ignore", "Client" };
int __cdecl DbgAllocHook ( int nAllocType,
void *pvData,
size_t nSize,
int nBlockUse,
long lRequest,
const unsigned char *pszFileName,
int nLine
)
{
char *pszFile = pszFileName ? ( char *) pszFileName : "<unknown>";
if ( _CRT_BLOCK == nBlockUse) // Ignore internal C runtime library allocations
return( TRUE);
_ASSERT( ( nAllocType > 0 ) && ( nAllocType < 4 ) );
_ASSERT( ( nBlockUse >= 0 ) && ( nBlockUse < 5 ) );
DbgTrace ( "Memory operation in %s, line %d: %s a %d-byte '%s' block (# %ld)",
pszFile,
nLine,
g_apszMemOperation [ nAllocType],
nSize,
g_apszMemBlockType [ nBlockUse],
lRequest
);
if ( pvData)
DbgTrace ( "at 0x%x\n", pvData);
else DbgTrace ( "\n");
return( TRUE); // Allow the memory operation to proceed
}
void __cdecl DbgTrace ( char *pszFormat, ...)
{
va_list args;
va_start( args, pszFormat);
char acModule [ MAX_PATH];
DWORD dwRC;
EnterCriticalSection ( &g_csDbg);
dwRC = wvsprintf ( g_acDbgBuf,
pszFormat,
args
);
_ASSERTE ( DBG_BUFSIZE >= dwRC);
dwRC = GetModuleFileName ( NULL,
acModule,
MAX_PATH
);
_ASSERTE ( MAX_PATH >= dwRC);
_CrtDbgReport ( _CRT_WARN,
NULL,
NULL,
acModule,
g_acDbgBuf
);
LeaveCriticalSection ( &g_csDbg);
va_end ( args);
}