Мы получили от клиента собственный (полный) файл аварийного дампа. Открытие его в отладчике Visual Studio (2005) показывает, что у нас был сбой, вызванный вызовом realloc, который пытался выделить блок размером 10 МБ. Файл дампа был необычайно большим (1,5 ГБ - обычно они больше похожи на 500 МБ).
Таким образом, мы заключаем, что у нас есть память "утечка" или "беглые выделения", которые либо полностью исчерпали память процесса, либо, по крайней мере, фрагментировали его достаточно значительно для сбоя realloc. (Обратите внимание, что этот realloc был для операции, которая распределяла буфер регистрации, и мы не удивлены, что она не сработала здесь, потому что 10 МБ за один раз будет одним из больших распределений, которые мы делаем отдельно от некоторых очень больших довольно неизменных буферов - - сама проблема, вероятно, не имеет ничего общего с этим конкретным распределением.)
Изменить: После обмена комментариями с Lex Lex ниже, я должен добавить: Это не воспроизводится для нас (на данный момент). Это всего лишь один дамп клиента, который явно показывает потребление памяти беглых.
Основной вопрос:
Теперь у нас есть файл дампа, но как мы можем определить, что вызвало чрезмерное использование памяти?
Что мы сделали до сих пор:
Мы использовали инструмент 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 или любого другого инструмента действительно могут помочь! Кроме того, если вы не согласны с каким-либо из моих анализов выше, дайте нам знать! Спасибо!