2014-12-08 7 views
-2

У меня проблема с сервером ATL COM, который использует много памяти с течением времени. Я подозреваю утечку памяти, но я не могу точно определить причину. Служба медленно добавляет память в течение 48-часового стресс-теста.C++ Использование памяти сервера COM увеличивается с течением времени - analisys with WinDBG

Вот что я собрал в WinDBG, проанализировав процесс через 1 час. Я помещаю здесь некоторые объекты, которые занимают большую часть памяти.

size  #blocks  total  (%) (percent of total busy bytes) 
190  6c3  - a90b0 (32.86) 
30   1507  - 3f150 (12.26) 

!heap -flt s 190 

!heap -p -a 0000000002ae0ee0 
address 0000000002ae0ee0 found in 
_HEAP @ 1a40000 
      HEAP_ENTRY Size Prev Flags   UserPtr UserSize - state 
    0000000002ae0eb0 001c 0000 [00] 0000000002ae0ee0 00190 - (busy) 
     combase!CStdIdentity::`vftable' 
    7ffd1aa71be7 ntdll!RtlAllocateHeap+0x000000000006fb17 
    7ffd18676158 combase!CIDObject::GetOrCreateStdID+0x0000000000000128 
    7ffd1867a788 combase!CDestObjectWrapper::MarshalInterface+0x00000000000006ca 
    7ffd186795c2 combase!CoMarshalInterface+0x00000000000001a2 
    7ffd1868145f combase!MarshalHelperMulti+0x000000000000006f 
    7ffd1868139f combase!GetInstanceHelperMulti+0x0000000000000083 
    7ffd18681129 combase!CObjServer::CreateInstance+0x0000000000000467 
    7ffd18b02385 RPCRT4!Invoke+0x0000000000000065 
    7ffd18b0ae16 RPCRT4!NdrStubCall2+0x000000000000038b 
    7ffd18b170eb RPCRT4!NdrStubCall3+0x000000000000014a 
    7ffd187a05ff combase!CStdStubBuffer_Invoke+0x0000000000000067 
    7ffd187a04d9 combase!SyncStubInvoke+0x0000000000000306 
    7ffd18633fc9 combase!CCtxComChnl::ContextInvoke+0x0000000000000279 
    7ffd187a13ff combase!AppInvoke+0x000000000000018f 
    7ffd187a0e9b combase!ComInvokeWithLockAndIPID+0x0000000000000661 
    7ffd187a184e combase!ThreadInvoke+0x0000000000000481 
    7ffd18b02614 RPCRT4!DispatchToStubInCNoAvrf+0x0000000000000014 
    7ffd18b02517 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x0000000000000177 
    7ffd18b16ebf RPCRT4!LRPC_SCALL::DispatchRequest+0x0000000000000531 
    7ffd18b02cc1 RPCRT4!LRPC_SCALL::HandleRequest+0x0000000000000201 
    7ffd18b02a97 RPCRT4!LRPC_SASSOCIATION::HandleRequest+0x0000000000000237 
    7ffd18b01d04 RPCRT4!LRPC_ADDRESS::ProcessIO+0x000000000000036d 
    7ffd18b01afe RPCRT4!LrpcIoComplete+0x00000000000000ae 
    7ffd1a9fd394 ntdll!TppAlpcpExecuteCallback+0x0000000000000204 
    7ffd1a9fb96d ntdll!TppWorkerThread+0x00000000000003ad 
    7ffd184f15bd KERNEL32!BaseThreadInitThunk+0x000000000000000d 
    7ffd1aa343d1 ntdll!RtlUserThreadStart+0x000000000000001d 

!heap -flt s 30 
!heap -p -a 0000000002af5960 
address 0000000002af5960 found in 
_HEAP @ 1a40000 
      HEAP_ENTRY Size Prev Flags   UserPtr UserSize - state 
    0000000002af5930 0006 0000 [00] 0000000002af5960 00030 - (busy) 
    7ffd1aa71be7 ntdll!RtlAllocateHeap+0x000000000006fb17 
    7ffd1a9e0056 ntdll!RtlpAddDebugInfoToCriticalSection+0x0000000000000012 
    7ffd1aa79db4 ntdll!RtlInitializeCriticalSectionAndSpinCount+0x0000000000055dd4 
    7ffd18674b24 combase!CStdIdentity::CStdIdentity+0x00000000000002d4 
    7ffd1867618d combase!CIDObject::GetOrCreateStdID+0x000000000000015d 
    7ffd1867a788 combase!CDestObjectWrapper::MarshalInterface+0x00000000000006ca 
    7ffd186795c2 combase!CoMarshalInterface+0x00000000000001a2 
    7ffd1868145f combase!MarshalHelperMulti+0x000000000000006f 
    7ffd1868139f combase!GetInstanceHelperMulti+0x0000000000000083 
    7ffd18681129 combase!CObjServer::CreateInstance+0x0000000000000467 
    7ffd18b02385 RPCRT4!Invoke+0x0000000000000065 
    7ffd18b0ae16 RPCRT4!NdrStubCall2+0x000000000000038b 
    7ffd18b170eb RPCRT4!NdrStubCall3+0x000000000000014a 
    7ffd187a05ff combase!CStdStubBuffer_Invoke+0x0000000000000067 
    7ffd187a04d9 combase!SyncStubInvoke+0x0000000000000306 
    7ffd18633fc9 combase!CCtxComChnl::ContextInvoke+0x0000000000000279 
    7ffd187a13ff combase!AppInvoke+0x000000000000018f 
    7ffd187a0e9b combase!ComInvokeWithLockAndIPID+0x0000000000000661 
    7ffd187a184e combase!ThreadInvoke+0x0000000000000481 
    7ffd18b02614 RPCRT4!DispatchToStubInCNoAvrf+0x0000000000000014 
    7ffd18b02517 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x0000000000000177 
    7ffd18b16ebf RPCRT4!LRPC_SCALL::DispatchRequest+0x0000000000000531 
    7ffd18b02cc1 RPCRT4!LRPC_SCALL::HandleRequest+0x0000000000000201 
    7ffd18b02a97 RPCRT4!LRPC_SASSOCIATION::HandleRequest+0x0000000000000237 
    7ffd18b01d04 RPCRT4!LRPC_ADDRESS::ProcessIO+0x000000000000036d 
    7ffd18b01afe RPCRT4!LrpcIoComplete+0x00000000000000ae 
    7ffd1a9fd394 ntdll!TppAlpcpExecuteCallback+0x0000000000000204 
    7ffd1a9fb96d ntdll!TppWorkerThread+0x00000000000003ad 
    7ffd184f15bd KERNEL32!BaseThreadInitThunk+0x000000000000000d 
    7ffd1aa343d1 ntdll!RtlUserThreadStart+0x000000000000001d 

Другие объекты:

size  #blocks  total  (%) (percent of total busy bytes) 
48  6c2  - 1e690 (91.91) 
1000  1  - 1000 (3.02) 

!heap -flt s 48 
!heap -p -a 0000000002ab8000 
address 0000000002ab8000 found in 
_HEAP @ 1a40000 
      HEAP_ENTRY Size Prev Flags   UserPtr UserSize - state 
    0000000002ab7fd0 0007 0000 [00] 0000000002ab8000 00048 - (busy) 
     combase!g_ForwardingVtbl 
    7ffd1aa71be7 ntdll!RtlAllocateHeap+0x000000000006fb17 
    7ffd18674115 combase!CreateStubFromTypeInfo+0x0000000000000061 
    7ffd18b58f63 RPCRT4!CreateStubFromTypeInfo+0x0000000000000043 
    7ffd1908dcf8 OLEAUT32!CUnivStubWrapper::Invoke+0x0000000000000098 
    7ffd187a04d9 combase!SyncStubInvoke+0x0000000000000306 
    7ffd18633fc9 combase!CCtxComChnl::ContextInvoke+0x0000000000000279 
    7ffd187a13ff combase!AppInvoke+0x000000000000018f 
    7ffd187a0e9b combase!ComInvokeWithLockAndIPID+0x0000000000000661 
    7ffd187a184e combase!ThreadInvoke+0x0000000000000481 
    7ffd18b02614 RPCRT4!DispatchToStubInCNoAvrf+0x0000000000000014 
    7ffd18b02517 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x0000000000000177 
    7ffd18b16ebf RPCRT4!LRPC_SCALL::DispatchRequest+0x0000000000000531 
    7ffd18b02cc1 RPCRT4!LRPC_SCALL::HandleRequest+0x0000000000000201 
    7ffd18b02a97 RPCRT4!LRPC_SASSOCIATION::HandleRequest+0x0000000000000237 
    7ffd18b01d04 RPCRT4!LRPC_ADDRESS::ProcessIO+0x000000000000036d 
    7ffd18b01afe RPCRT4!LrpcIoComplete+0x00000000000000ae 
    7ffd1a9fd394 ntdll!TppAlpcpExecuteCallback+0x0000000000000204 
    7ffd1a9fb96d ntdll!TppWorkerThread+0x00000000000003ad 
    7ffd184f15bd KERNEL32!BaseThreadInitThunk+0x000000000000000d 
    7ffd1aa343d1 ntdll!RtlUserThreadStart+0x000000000000001d 

!heap -p -a 000000000282f280 
address 000000000282f280 found in 
_HEAP @ 20a0000 
      HEAP_ENTRY Size Prev Flags   UserPtr UserSize - state 
    000000000282f250 0007 0000 [00] 000000000282f280 00048 - (busy) 
     ccprovsp!ATL::CComObject<MyCOM>::`vftable' 
    7ffd1aa71be7 ntdll!RtlAllocateHeap+0x000000000006fb17 
    140028c87 ccprovsp!malloc+0x0000000000000067 
    14002815e ccprovsp!operator new+0x000000000000000e 
    14000280b ccprovsp!ATL::CComCreator<ATL::CComObject<MyCOM> >::CreateInstance+0x000000000000005b 
    14000239c ccprovsp!ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<MyCOM> >,ATL::CComFailCreator<-2147221232> >::CreateInstance+0x000000000000002c 
    1400085a7 ccprovsp!ATL::CComClassFactory::CreateInstance+0x0000000000000077 
    7ffd1868134c combase!GetInstanceHelperMulti+0x0000000000000034 
    7ffd18681129 combase!CObjServer::CreateInstance+0x0000000000000467 
    7ffd18b02385 RPCRT4!Invoke+0x0000000000000065 
    7ffd18b0ae16 RPCRT4!NdrStubCall2+0x000000000000038b 
    7ffd18b170eb RPCRT4!NdrStubCall3+0x000000000000014a 
    7ffd187a05ff combase!CStdStubBuffer_Invoke+0x0000000000000067 
    7ffd187a04d9 combase!SyncStubInvoke+0x0000000000000306 
    7ffd18633fc9 combase!CCtxComChnl::ContextInvoke+0x0000000000000279 
    7ffd187a13ff combase!AppInvoke+0x000000000000018f 
    7ffd187a0e9b combase!ComInvokeWithLockAndIPID+0x0000000000000661 
    7ffd187a184e combase!ThreadInvoke+0x0000000000000481 
    7ffd18b02614 RPCRT4!DispatchToStubInCNoAvrf+0x0000000000000014 
    7ffd18b02517 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x0000000000000177 
    7ffd18b16ebf RPCRT4!LRPC_SCALL::DispatchRequest+0x0000000000000531 
    7ffd18b02cc1 RPCRT4!LRPC_SCALL::HandleRequest+0x0000000000000201 
    7ffd18b02a97 RPCRT4!LRPC_SASSOCIATION::HandleRequest+0x0000000000000237 
    7ffd18b01d04 RPCRT4!LRPC_ADDRESS::ProcessIO+0x000000000000036d 
    7ffd18b01afe RPCRT4!LrpcIoComplete+0x00000000000000ae 
    7ffd1a9fd394 ntdll!TppAlpcpExecuteCallback+0x0000000000000204 
    7ffd1a9fb96d ntdll!TppWorkerThread+0x00000000000003ad 
    7ffd184f15bd KERNEL32!BaseThreadInitThunk+0x000000000000000d 
    7ffd1aa343d1 ntdll!RtlUserThreadStart+0x000000000000001d 

Любой намек на то, что я должен делать дальше?

+0

Управление жизненным циклом объекта в COM основано на подсчете ссылок. Трудно сказать, что вызвало утечку на основе стека вызовов. Попробуйте debugdiag вместо Windbg – Matt

ответ

0

Прежде всего, кажется, что вы правильно настроили GFlags для отслеживания выделения памяти. Это хорошо и определенно поможет найти проблему. Однако объекты, которые вы разместили, бессмысленны, потому что мы не можем сказать, должны ли они в настоящее время использоваться или нет.

Выполнение анализа в WinDbg довольно сложно и требует много ручной работы. К счастью, есть UMDH (MSDN), который будет полезен в таком сценарии.

Как действовать

Поскольку вы можете воспроизвести проблему в относительно короткий промежуток времени (600 кбайт в 1 час в порядке), сделать это. Создайте сценарий, в котором вы неоднократно достигаете одного и того же состояния в своем приложении и где (по вашему мнению) все память должна была быть снова освобождена. В течение одного часа всегда создавайте моментальный снимок UMDH, когда это состояние достигнуто. Позже проанализируйте файлы журнала (этот подход называется «Режим 2»).

UMDH сортирует все распределения памяти по стеке вызовов. Если вам удастся нарисовать график распределений с течением времени, например. в Excel вы, вероятно, увидите одну линию, которая растет. Это потенциально преступник. Вы можете попробовать HeapProfiler для создания такого графика (я никогда не использовал это раньше, так как у меня есть собственный инструмент для создания графика, к сожалению, он не готов к выпуску в это время).

Когда вы знаете тип объекта, который затерялся, вы знаете, где он выделен (из стека вызовов). Затем выполните обзор кода и найдите место, где оно должно быть выпущено. Попытайтесь понять, почему он не выпущен (и это действительно тяжелая часть).

Дальнейшее чтение

Inside Windows Debugging (Amazaon) Книга по Тарик Soulami охватывает UMDH в главе 8.

Вы также можете читать или слушать некоторые электронные учебники, например Using UMDH to Find a User-Mode Memory Leak или Finding Memory Leaks with UMDH.

Смежные вопросы