Используя WinDbg, возможно ли выделить исходную строку в исходном коде MFC с помощью команды WinDbg? - PullRequest
0 голосов
/ 19 сентября 2019

Справочная информация:

Иногда я получаю утечки в моих программах MFC dApp , находящихся в стадии разработки.MFC красиво выводит обнаруженные блоки утечки на панель вывода в Visual Studio, показывая их {номер блока} и шестнадцатеричный адрес.Некоторые утечки не имеют путей к исходным файлам и номеров строк, кроме fx strcore.cpp и т. Д. Эти источники утечек трудно найти и нуждаются в лучшем решении.

Изучая WinDbg Preview с его отладкой во времени (TTD), я могу понять, как это будет правильным инструментом для быстрого поиска утечек MFC.

Тест поиска утечек:

Я создал небольшую программу MFC и добавил в нее утечку:

void LeakInThread()
{
  int* intLeak = new int[ 500 ];
}

wchar* leak = new wchar[ 100 ];
std::thread t1( LeakInThread ); // added leak in thread
t1.join();   

Программа произвела: {274698} normal block at 0x000001AFA34D9790, 200 bytes long.

Используя WinDbg, я создал файл трассировки, время, пройденное доконец, чтобы убедиться, что утечка была создана, и использовал WinDbg commnd !heap -i x000001AFA34D9790, чтобы найти блок TTD, где произошла ошибка.Вот вывод:

0:000> !heap -i 0x00000180F42E3790 Detailed information for block entry 00000180f42e3790 Assumed heap : 0x0000000000000000 (Use !heap -i NewHeapHandle to change) Header content : 0xCDCDCDCD 0xCDCDCDCD Block flags : 0x1 LFH (busy ) Total block size : 0x0 units (0x0 bytes) Requested size : 0xffffec00 bytes (unused 0x1400 bytes) Subsegment : 0x25dac2f1e46abc2eUser blocks not available

Вопрос: Существуют ли команды WinDbg, которые показывают мне файл и номер строки в исходной панели WinDbg?

Edit1:

Экспериментировал с этой командой запроса:

dx -g @$MemRes = @$cursession.TTD.Resources.HeapMemory

и получил:

======================================================================================================================================
=           = ResourceId       = ResourceIdNew    = Size    = Function                   = ThreadId  = UniqueThreadId = Position     =
======================================================================================================================================
= [0x0]     - 0x180f4282870    - 0x0              - 0x4c    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - C819:58      =
= [0x1]     - 0x180f42b79d0    - 0x0              - 0x48    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - 5545:62      =
= [0x2]     - 0x180f4282870    - 0x0              - 0x0     - ntdll!RtlFreeHeap          - 0x59e4    - 0x2            - C827:13F     =
= [0x3]     - 0x180f42b32a0    - 0x0              - 0x6a    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - 2E1C:58      =
= [0x4]     - 0x180f744d330    - 0x0              - 0x24    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - 9609:4C      =
= [0x5]     - 0x180f74572e0    - 0x0              - 0x48    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - 960C:20D     =
= [0x6]     - 0x180f42b32a0    - 0x0              - 0x0     - ntdll!RtlFreeHeap          - 0x59e4    - 0x2            - 2E23:147     =
= [0x7]     - 0x180f42c1990    - 0x0              - 0x6a    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - FB23:58      =
= [0x8]     - 0x180f42d9fd0    - 0x0              - 0x0     - ntdll!RtlFreeHeap          - 0x59e4    - 0x2            - 12D1B:13F    =
= [0x9]     - 0x180f42c1990    - 0x0              - 0x0     - ntdll!RtlFreeHeap          - 0x59e4    - 0x2            - FB2A:147     =
= [0xa]     - 0x180f7453160    - 0x0              - 0x30    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - 9625:4C      =
= [0xb]     - 0x180f42c0810    - 0x0              - 0x6a    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - FB2E:58      =
= [0xc]     - 0x180f42b9160    - 0x0              - 0x0     - ntdll!RtlFreeHeap          - 0x59e4    - 0x2            - 2E25:4B      =
= [0xd]     - 0x180f42e9bd0    - 0x0              - 0x0     - ntdll!RtlFreeHeap          - 0x59e4    - 0x2            - 15481:13F    =
= [0xe]     - 0x180f42d9fd0    - 0x0              - 0x4c    - ntdll!RtlAllocateHeap      - 0x59e4    - 0x2            - 12D0D:58     =
= [...]

С ResourceID выглядит как выходной адрес MFC, я сузил вывод с помощью этого запроса выбора:

dx -g @$MemRes.Where(x => x.ResourceId == 0x00000180F42E3790)

, но сетка вывода не имеет результатов.

Edit2:

"Если утечка произошла в потоке MainFrame, также отображаются исходный файл и номер строки. Нет, если утечка произошла в другом порожденном потоке."неправда.Но происходят утечки, которые не указывают на их источник и номера строк.Все еще существует вероятность того, что в программе отладчика MFC отсутствует какой-либо исходный путь, позволяющий найти исходный код.Требуются дополнительные исследования.

Edit3:

При дальнейшем рассмотрении утечки, вызванные моей программой MFC, даже без нажатия клавиш после запуска, имеют разные адреса данных каждыйВремя бежит.(Утечки были введены много раз назад, незаметно до сих пор).Это означает, что я не могу использовать команду WinDbg TTD dx ... для итерации по кадрам трассировки, сравнивая адреса данных с кадром LocalVariables Values просто потому, что адреса данных утечек будут отличаться при каждом запуске программы, в том числе когдаТрассировка записывается.Но, тем не менее, команды могут использоваться для определения того, будет ли выделение кучи незавершенным при закрытии программы.

1 Ответ

2 голосов
/ 20 сентября 2019

Как прокомментировано, я не уверен, что вы ищете, это несколько вариантов, которые вы можете попробовать

1) вы можете изменить параметры .asm, чтобы в списке разборки отображался номер строки и имя файла

как показано ниже

.asm

1:001> .asm
Assembly options: <default>
1:001> u .
vect!main [f:\src\vect\vect.cpp @ 9]:
00007ff6`e1d7efb0 4881ec98000000  sub     rsp,98h
00007ff6`e1d7efb7 48c7442460feffffff mov   qword ptr [rsp+60h],0FFFFFFFFFFFFFFFEh
00007ff6`e1d7efc0 488d4c2448      lea     rcx,[rsp+48h]
00007ff6`e1d7efc5 e8576dffff      call    vect!ILT+19740(??0?
00007ff6`e1d7efca 90              nop
00007ff6`e1d7efcb c744242001000000 mov     dword ptr [rsp+20h],1
00007ff6`e1d7efd3 eb0a            jmp     vect!main+0x2f (00007ff6`e1d7efdf)
00007ff6`e1d7efd5 8b442420        mov     eax,dword ptr [rsp+20h]
1:001> .asm source_line
Assembly options: source_line
1:001> u .
vect!main [f:\src\vect\vect.cpp @ 9]:
    9 00007ff6`e1d7efb0 4881ec98000000  sub     rsp,98h
    9 00007ff6`e1d7efb7 48c7442460feffffff mov   qword ptr [rsp+60h],0FFFFFFFFFFFFFFFEh
   10 00007ff6`e1d7efc0 488d4c2448      lea     rcx,[rsp+48h]
   10 00007ff6`e1d7efc5 e8576dffff      call    vect!ILT+19740(??0?
   10 00007ff6`e1d7efca 90              nop
   12 00007ff6`e1d7efcb c744242001000000 mov     dword ptr [rsp+20h],1
   12 00007ff6`e1d7efd3 eb0a            jmp     vect!main+0x2f (00007ff6`e1d7efdf)
   12 00007ff6`e1d7efd5 8b442420        mov     eax,dword ptr [rsp+20h]

или вы можете использовать .open -a адрес, чтобы открыть новое окно источника

, например

.open -a.

открывает источник, соответствующий текущему Rip / Eip.(точка) обозначает текущий указатель инструкций

или вы можете использовать команды ls для

печати исходных строк (используйте lsp для настройки количества строк до и после строки по умолчанию - 5 строк до 5 строк после)

1:001> lsa .
     5: 
     6: using namespace std; 
     7: 
     8: int main() 
>    9: { 
    10:     vector<int> g1; 
    11: 
    12:     for (int i = 1; i <= 5; i++) 
    13:         g1.push_back(i); 
    14: 
...