Мы получили собственный (полный) файл аварийного дампа от клиента. Открытие его в отладчике Visual Studio (2005) показывает, что у нас произошел сбой, вызванный вызовом realloc, который пытался выделить блок размером ~ 10 МБ. Файл дампа был необычно большим (1,5 ГБ - обычно они больше похожи на 500 МБ).
Поэтому мы пришли к выводу, что у нас есть «утечка» памяти или неконтролируемые выделения, которые либо полностью исчерпали память процесса, либо, по крайней мере, существенно фрагментировали ее, чтобы произошел сбой realloc. (Обратите внимание, что этот realloc был для операции, которая выделяла буфер журналирования, и мы не удивлены, что он потерпел неудачу здесь, потому что 10 МБ за один раз было бы одним из больших выделений, которые мы делаем, за исключением некоторых очень больших довольно неизменных буферов - - сама проблема, скорее всего, не имеет ничего общего с этим конкретным распределением.)
Редактировать: После обмена комментариями с Лексом Ли ниже я должен добавить: невоспроизводимо для нас (на данный момент). Это всего лишь один клиент дамп, ясно показывающий потребление неуправляемой памяти.
Основной вопрос:
Теперь у нас есть файл дампа, но как мы можем определить причину чрезмерного использования памяти?
Что мы сделали до сих пор:
Мы использовали инструмент DebugDiag для анализа файла дампа (так называемый анализатор памяти), и вот что мы получили:
Report for DumpFM...dmp
Virtual Memory Summary
----------------------
Size of largest free VM block 62,23 MBytes
Free memory fragmentation 81,30%
Free Memory 332,87 MBytes (16,25% of Total Memory)
Reserved Memory 0 Bytes (0,00% of Total Memory)
Committed Memory 1,67 GBytes (83,75% of Total Memory)
Total Memory 2,00 GBytes
Largest free block at 0x00000000`04bc4000
Loaded Module Summary
---------------------
Number of Modules 114 Modules
Total reserved memory 0 Bytes
Total committed memory 3,33 MBytes
Thread Summary
--------------
Number of Threads 56 Thread(s)
Total reserved memory 0 Bytes
Total committed memory 652,00 KBytes
Это просто чтобы получить немного контекста. Я думаю, что интереснее:
Heap Summary
------------
Number of heaps 26 Heaps
Total reserved memory 1,64 GBytes
Total committed memory 1,61 GBytes
Top 10 heaps by reserved memory
-------------------------------
0x01040000 1,55 GBytes
0x00150000 64,06 MBytes
0x010d0000 15,31 MBytes
...
Top 10 heaps by committed memory
--------------------------------
0x01040000 1,54 GBytes
0x00150000 55,17 MBytes
0x010d0000 6,25 MBytes
...
Теперь, глядя на кучу 0x01040000
(1,5 ГБ) мы видим:
Heap 5 - 0x01040000
-------------------
Heap Name msvcr80!_crtheap
Heap Description This heap is used by msvcr80
Reserved memory 1,55 GBytes
Committed memory 1,54 GBytes (99,46% of reserved)
Uncommitted memory 8,61 MBytes (0,54% of reserved)
Number of heap segments 39 segments
Number of uncommitted ranges 41 range(s)
Size of largest uncommitted range 8,33 MBytes
Calculated heap fragmentation 3,27%
Segment Information
-------------------
Base Address | Reserved Size | Committed Size | Uncommitted Size | Number of uncommitted ranges | Largest uncommitted block | Calculated heap fragmentation
0x01040640 64,00 KBytes 64,00 KBytes 0 Bytes 0 0 Bytes 0,00%
0x01350000 1.024,00 KBytes 1.024,00 KBytes 0 Bytes 0 0 Bytes 0,00%
0x02850000 2,00 MBytes 2,00 MBytes 0 Bytes 0 0 Bytes 0,00%
...
Что это за информация о сегменте?
Просмотр перечисленных ассигнований:
Top 5 allocations by size
-------------------------
Allocation Size - 336 1,18 GBytes
Allocation Size - 1120004 121,77 MBytes
...
Top 5 allocations by count
--------------------------
Allocation Size - 336 3760923 allocation(s)
Allocation Size - 32 1223794 allocation(s)
...
Мы можем видеть, что, очевидно, куча MSVCR80 содержит 3.760.923 выделения в 336 байтов. Это довольно ясно дает понять, что мы зарезервировали нашу память большим количеством небольших выделений, но как мы можем получить больше информации о том, откуда взято это выделение ?
Если бы мы каким-то образом могли выбрать некоторые из этих адресов распределения и затем проверить, где в образе процесса эти адреса используются, тогда - предполагая, что большая часть этих распределений ответственна за нашу "утечку" - мы могли бы возможно узнайте, откуда взялись эти побеги.
К сожалению, я действительно не знаю, как получить больше информации из дампа в данный момент.
Как я могу проверить эту кучу, чтобы увидеть некоторые из "336" адресов распределения?
Как я могу найти в дампе эти адреса и как мне узнать, какая переменная указателя (если есть) в дампе удерживает эти адреса?
Любые советы, касающиеся использования DebugDiag, WinDbg или любого другого инструмента, могут действительно помочь! Кроме того, если вы не согласны с любым из моего анализа выше, сообщите нам! Спасибо!