
Роббинс Д. - Отладка приложений для Microsoft .NET и Microsoft Windows - 2004
.pdfГЛАВА 8 Улучшенные приемы для неуправляемого кода с использованием WinDBG |
361 |
|
|
вывода будет открыт, WinDBG автоматически получает, что было записано, и вы можете начинать просматривать файл дампа.
Если вы создавали дамп на той же машине, где собирали процесс, ваша жизнь весьма проста, так как WinDBG проделает всю работу по получению символов и информации о номерах строк исходного кода. Однако большинство из нас будут анализировать файлы дампа, созданные на других машинах и других версиях ОС. После открытия файла дампа начинается работа по получению символов, настройке путей к исходному коду и исполняемым модулям.
Во!первых, определите, в каких модулях пропущена информация о символах, запустив команду LM с ключом v. Если какие!то модули сообщают «no symbols loaded» (символы не загружены), надо настроить путь для поиска символов. Посмотрите на информацию о версиях, ассоциированную с этими модулями, и соответствен! но обновите Symbol File Path (путь к файлу символов), выбрав Symbol File Path в меню File.
Второй шаг — настройка путей к файлам исполняемых образов. Как я уже го! ворил в главе 2, WinDBG нужен доступ к двоичным файлам до того, как он смо! жет загрузить символы для минидампов. Если вы следовали моим рекомендаци! ям и поместили свои программы и необходимые различным ОС двоичные фай! лы и символы в свой сервер символов, подключить двоичные файлы легко. В ди! алоговом окне Executable Image Search Path (путь к исполняемому образу), дос! тупном при выборе Image File Path (путь к файлу образа) меню File, можно про! сто вставить из буфера обмена ту же строку, что вы указали для символьного сер! вера. WinDBG автоматически найдет ваш сервер символов для соответствующих двоичных файлов.
Если двоичных файлов в хранилище символов нет, нужно указать путь вруч! ную и надеяться, что вы указали его к корректным версиям модулей. Это особен! но трудно с двоичными файлами ОС, так как очередное исправление может из! менить любое их количество. В действительности, каждый раз, внося «горячие» изменения или устанавливая пакет обновлений, вы должны перезагрузить свое хранилище символов, запустив файл OSSYMS.JS (см. главу 2).
И наконец, необходимо настроить путь к исходным текстам, выбрав Source File Path (путь к исходному файлу) из меню File. Настроив все три пути, перезагрузи! те символы командой .RELOAD /f, после которой последует команда LM, позволяю! щая увидеть все еще некорректные символы. Если минидамп доставлен от заказ! чика, вам, возможно, не удастся загрузить все двоичные файлы и символы, так как там может оказаться другой уровень внесенных исправлений или программ тре! тьих поставщиков, напихавших кучу DLL в другие процессы. Однако ваша цель — загрузить все символы ваших программ и как можно больше символов ОС. Как! никак, если вам удалось загрузить все символы, отладка становится простым делом!
Отладка дампа
Если вам удалось корректно загрузить символы и двоичные файлы, то отладка файла дампа почти идентична отладке «живьем». Очевидно, что некоторые команды, такие как BU, не будут работать с файлами дампа, но большинство других будет, особен!

362 ЧАСТЬ II Производительная отладка
но команды расширения. При возникновении проблем с командами, обратитесь к таблице окружения в документации по этой команде и проверьте, что вы може! те использовать ее при отладке файлов дампа.
Если вы имеете несколько файлов дампа сразу, вы также можете отлаживать их совместно командой .OPENDUMP (Open Dump File — открыть файл дампа). От! крыв файл дампа таким способом, необходимо дать команду G (Go — запустить), чтобы WinDBG смог все запустить.
Наконец, команда, доступная только при отладке файла дампа, — .DUMPCAB (Create Dump File CAB — создать CAB файл дампа) — создаст .CAB!файл из текущего фай! ла дампа. Если вы добавите параметр –a, все символы будут записаны в этот файл.
Son of Strike (SOS)
Имеется замечательная поддержка для отладки дампов приложений неуправляе! мого кода, но не для приложений управляемого кода, и, хотя управляемые прило! жения меньше подвержены появлению в них ошибок, отлаживать их гораздо труд! нее. Рассмотрим, например, те проекты, в которые были произведены значитель! ные вложения в COM+ или другие технологии неуправляемого кода. Вы можете и хотите создавать новые внешние интерфейсы в .NET или компоненты, усиливаю! щие ваши COM!компоненты путем использования COM interop. Когда эти прило! жения завершаются аварийно или зависают, вы тут же получаете головную боль, так как почти невозможно продраться сквозь ассемблерный код, исследовать стеки вызовов и даже найти исходные тексты и строки для этих .NET!частей прило! жения.
Чтобы помочь вам увидеть .NET!части дампа или «живого» приложения, неко! торые очень умные люди в Microsoft сделали расширение отладчика, названное SOS или Son of Strike («Дитя забастовки»). Основная документация находится в файле SOS.HTM в каталоге <Каталог установки Visual Studio .NET >\SDK\v1.1\Tool Developers Guide\Samples\SOS. Там вы определенно увидите, что «основная» — это действительно работающий термин. В сущности это список команд расширения SOS.DLL и краткие сведения об их использовании.
Если вы работаете с большими системами .NET, особенно с тяжелыми тран! закциями ASP.NET, вам также захочется загрузить 170!страничный PDF!файл «Pro! duction Debugging for .NET Framework Applications» (Отладка промышленных при! ложений для .NET Framework) с http://msdn.microsoft.com/library/default.asp?url=/ library/en!us/dnbda/html/DBGrm.asp. Если вы хотите знать, как управлять завис! шими процессами ASNET_WP.EXE, работать с потенциальными проблемами управ! ления памятью в .NET и контролировать другие экстремально!пограничные про! блемы, это прекрасный документ. Его авторы определенно отладили массу жиз! ненных систем промышленного уровня, и их знание поможет вам преодолеть многие трудности.
Вы кратко познакомитесь с командами SOS, основываясь на этих двух доку! ментах и документе сверхоткровенных трюков, но вот как начать работать с SOS внутри WinDBG, там не сказано. В этом разделе я хочу помочь вам сделать пер! вые шаги. Надеюсь, вы узнаете здесь достаточно, чтобы понимать документ «Produc! tion Debugging for .NET Framework Applications». Я не охвачу всего, например, всех
ГЛАВА 8 Улучшенные приемы для неуправляемого кода с использованием WinDBG |
363 |
|
|
команд сборщика мусора, так как они рассмотрены в «Production Debugging for
.NET Framework Applications».
Прежде всего я хочу показать простой способ загрузить SOS.DLL в WinDBG. SOS.DLL является частью собственно .NET Framework, поэтому фокус в том, что! бы включить нужные каталоги в ваш путь поиска (переменная окружения PATH), чтобы WinDBG справился с загрузкой SOS.DLL. Вам надо открыть командную строку MS!DOS и выполнить VSVARS32.BAT, находящийся в каталоге <Каталог установки Visual Studio .NET >\Common7\Tools. VSVARS32.BAT настраивает вашу среду так, что все соответствующие каталоги .NET будут включены в ваш путь поиска.
После однократного исполнения VSVARS32.BAT вы получаете возможность за! грузить SOS.DLL командой .load sos из окна Command WinDBG. WinDBG всегда помещает последнее загруженное расширение на верхушку цепочки, поэтому команда !help покажет вам краткий список всех команд SOS.DLL.
Использование SOS
Возможно, лучше всего показать, как пользоваться SOS, на примере. Программа ExpectApp из набора файлов к этой книге покажет вам, как подступиться к важ! ным командам. Чтобы сохранить изложение на приемлемом уровне, я написал этот код, чтобы просто вызвать несколько методов с локальными переменными и в конце вызвать исключительную ситуацию. Я пройду через отладку примера EXCEPT! APP.EXE с помощью SOS, чтобы вы увидели, какие команды помогут узнать, где вы находитесь, когда приложение, использующее управляемый код, валится или за! висает. Так вам будет проще применять SOS для решения проблем и понимать «Production Debugging for .NET Framework Applications»
Откомпилировав EXCEPTAPP.EXE и настроив переменные среды, как я описал выше, откройте EXCEPTAPP.EXE в WinDBG и остановитесь на точке прерывания загрузчика. Чтобы заставить WinDBG остановиться, когда приложение .NET вы! зовет исключительную ситуацию, надо сообщить WinDBG о номере исключения, сгенерированного .NET. Проще всего это можно сделать, щелкнув кнопку Add в диалоговом окне Event Filters и введя в диалоговом окне Exception Filter 0xE0434F4D. Затем выберите Enabled в группе Execution и Not Handled в группе Continue. Щел! кнув OK, вы успешно настроите WinDBG так, чтобы он останавливался каждый раз, когда вырабатывается исключение .NET. Если значение 0xE0434F4D кажется чем!то знакомым, узнать, что это такое, поможет команда .formats.
Настроив исключения, запустите EXCEPTAPP.EXE, пока она не остановится на исключении .NET. WinDBG сообщит о нем, как о первом исключении, и остано! вит приложение на реальном вызове Win32 API RaiseException. Загрузив SOS ко! мандой .load sos, выполните !threads (ее вы всегда будете хотеть исполнять пер! вой в SOS) и вы увидите, какие потоки в приложении или дампе имеют код .NET. В случае EXCEPTAPP.EXE команда потоков WinDBG ~ указывает, что в приложении исполняются три команды. Однако команда всеобщей важности !threads показы! вает, что только потоки 0 и 2 имеют некоторый код .NET (чтобы все поместилось на странице, я привожу информацию индивидуальных потоков в виде таблицы, в WinDBG вы видите это как длинные горизонтальные строки):

364 ЧАСТЬ II Производительная отладка
0:000> !threads
PDB symbol for mscorwks.dll not loaded succeeded
Loaded Son of Strike data table version 5 from "e:\WINNT\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll" ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Row Heading
WinDBG Thread ID 0 2
Win32 Thread ID 884 9dc
ThreadObj 00147c60 001631c8
State 20 1220
PreEmptive GCEnabled Enabled
GC Alloc Context 04a45f24:04a45ff4 00000000:00000000
Domain 00158300 00158300
Lock Count 0 0
APT Ukn Ukn
Exception System.ArgumentException (Finalizer)
Важная информация в отображении команды !threads содержит поле Domain (домен), говорящее о том, много ли доменов приложения (AppDomain) исполня! ется в рамках процесса, и поле Exceptions, которое оказывается перегруженным. В примере EXCEPTAPP.EXE первый поток вызвал System.ArgumentException, поэтому вы можете видеть текущее исключение для любого потока. Третий поток EXCEPT! APP.EXE показывает специальное значение (Finalizer), обозначающее, как вы можете полагать, завершающий поток процесса. Вы также увидите (Theadpool Worker), (Threadpool Completion Port) или (GC) в поле Exception. Когда вы видите одно из этих специальных значений, знайте, что они представляют потоки времени исполне! ния, а не ваши потоки.
Так как мы определили, что поток WinDBG 0 содержит исключение EXCEPT! APP.EXE, вы захотите взглянуть на стек вызовов с помощью !clrstack –all, чтобы увидеть все детали стека, включая параметры и локальные переменные. Хотя !clrstack имеет ключи для просмотра локальных переменных ( l) и параметров ( p), не указывайте их вместе, иначе они аннулируют друг друга. Чтобы увидеть весь стек вызовов сразу, дайте команду ~*e !clrstack.
** Имейте в виду, что я вырезал отсюда регистры ** 0:000> !clrstack –all
Thread 0
ESP EIP
0012f5e0 77e73887 [FRAME: HelperMethodFrame]
0012f60c 06d3025f [DEFAULT] [hasThis] Void ExceptApp.DoSomething.Doh (String,ValueClass ExceptApp.Days)
ГЛАВА 8 |
Улучшенные приемы для неуправляемого кода с использованием WinDBG |
365 |
|
|
|
at [+0x67] [+0x16] c:\junk\cruft\exceptapp\class1.cs:14 |
|
|
PARAM: this: 0x04a41b5c (ExceptApp.DoSomething) |
|
|
PARAM: value class ExceptApp.Days StrParam |
|
|
PARAM: unsigned int8 ValueParam: 0x07 |
|
|
0012f630 |
06d301e2 [DEFAULT] [hasThis] Void ExceptApp.DoSomething.Reh |
|
(I4,String) at [+0x6a] [+0x2b] c:\junk\cruft\exceptapp\class1.cs:23
PARAM: this: 0x04a41b5c (ExceptApp.DoSomething)
PARAM: class System.String i: 0x00000042
PARAM: int8 StrParam: 77863812
LOCAL: class System.String s: 0x04a45670 (System.String)
LOCAL: value class ExceptApp.Days e: 0x003e5278 0x0012f63c
Похоже, в отображении параметров есть ошибка, так как команда !clrstack не всегда корректно отображает тип параметра. В методе DoSomething.Doh вы можете увидеть, что он принимает значения String (StrParam) и Days (ValueParam). Однако информация PARAM: показывает параметр StrParam как value class ExceptApp.Days и ValueParam как unsigned int8. К счастью для параметров размерного типа, даже ког! да тип их неверен, рядом с именем параметра отображается его корректное зна! чение. В примере с ValueParam переданное значение 7 соответствует перечисле! нию Fri.
Прежде чем перейти к постижению значений размерных классов и объектов, я хочу отметить одну команду просмотра стека, которую, возможно, вы найдете полезной. Если вы работаете над сложными вызовами между .NET и неуправляе! мым кодом, вам понадобится увидеть стек вызовов, включающий все, и в этом случае команда !dumpstack — ваш лучший друг. В целом она делает отличную работу, но, имея полную PDB!базу символов для .NET Framework, она могла бы делать ее луч! ше. Временами !dumpstack сообщает «Use alternate method which may not work» (воспользуйтесь альтернативным методом, так как этот может не работать), что, кажется, указывает на то, что производится попытка просмотреть стек при отсут! ствии информации о некоторых символах.
Строки LOCAL: показывают, что в DoSomething.Reh имеются две локальных пере! менных: s (объект String) и e (размерный класс Days). После каждого выводится шестнадцатеричный адрес, описывающий тип. Для размерного класса Days име! ются два числа 0x003E5278 и 0x0012F63C. Первое — таблица методов, второе — рас! положение значения в памяти. Чтобы увидеть это значение в памяти, просто дай! те команду распечатки содержимого памяти WinDBG, такую как dd 0x0012F63C.
Просмотр таблицы методов, описывающей данные метода, информацию о модуле и карту интерфейса среди всего прочего осуществляется командой SOS !dumpmt. Выполнение !dumpmt 0x003E5278 для примера EXCEPTAPP.EXE выводит:
0:000> !dumpmt 0x003e5278 EEClass : 06c03b1c
Module : 001521a0
Name: ExceptApp.Days
mdToken: 02000002 (D:\Dev\ExceptApp\bin\Debug\ExceptApp.exe) MethodTable Flags : 80000
Number of IFaces in IFaceMap : 3

366 ЧАСТЬ II Производительная отладка
Interface Map : 003e5380
Slots in VTable : 55
В таблице методов, отображаемой двумя первыми числами, видно, в каком модуле определен этот метод, а также класс исполняющей системы .NET. Для ин! терфейсов в документации SOS есть прекрасный пример, как пройтись по кар! там интерфейсов, и я бы одобрил ваше знакомство с ним. Если у вас есть горячее желание увидеть все методы в виртуальной таблице конкретного класса или объекта вместе с описателями методов, можно задать ключ md в команде перед значением таблицы методов. В случае EXCEPTAPP.EXE и ее размерного класса ExceptApp.Days, будут перечислены 55 методов. Как указывает документация SOS в разделе «How Do I… ?», просмотр дескрипторов методов полезен при установке точек прерыва! ния на конкретных методах.
Так как мы рассматриваем информацию класса и модуля для таблицы методов ExceptApp.Days, я сделаю небольшое отступление. Как только вы получите адрес класса исполняющей системы .NET, !dumpclass покажет вам все, что вы только могли по! желать узнать о классе, в том числе и информацию обо всех полях данных клас! са. Чтобы увидеть информацию о модуле, дайте команду !dumpmodule. В докумен! тации есть пример, как с помощью вывода !dumpmodule пройтись по памяти и най! ти классы и таблицы методов модуля.
Теперь, когда у нас есть основы размерного класса, взглянем осмысленно на локальную переменную s класса String в DoSomething.Reh:
LOCAL: class System.String s: 0x04a45670 (System.String)
Так как s — объект, то после имени переменной отображается только одно шестнадцатеричное значение — размещение объекта в памяти. С помощью команды !dumpobj вы увидите всю информацию об объекте:
0:000> !dumpobj 0x04a45670 |
|
|
|
|
||
Name: System.String |
|
|
|
|
|
|
MethodTable 0x79b7daf0 |
|
|
|
|
||
EEClass 0x79b7de3c |
|
|
|
|
|
|
Size 92(0x5c) bytes |
|
|
|
|
|
|
mdToken: 0200000f |
(e:\winnt\microsoft.net\framework\v1.1.4322\mscorlib.dll) |
|||||
String: Tommy can you see me? Can you see me? |
|
|
||||
FieldDesc*: 79b7dea0 |
|
|
|
|
||
MT |
Field |
Offset |
Type |
Attr |
Value |
Name |
79b7daf0 |
4000013 |
4 |
System.Int32 |
instance |
38 |
_arrayLength |
79b7daf0 |
4000014 |
8 |
System.Int32 |
instance |
37 |
m_stringLength |
79b7daf0 |
4000015 |
c |
System.Char |
instance |
54 |
m_firstChar |
79b7daf0 |
4000016 |
0 |
CLASS |
shared |
static |
Empty |
>> Domain:Value 00158298:04a412f8 << |
|
|
|
|||
79b7daf0 |
4000017 |
4 |
CLASS |
shared |
static |
WhitespaceChars |
>> Domain:Value 00158298:04a4130c << |
|
|
|
Значения некоторых полей MethodTable, EEClass и MT (или Method Table) мо! гут использоваться в командах, которые мы только что обсудили. Что касается членов полей, то !dumpobj для простых размерных типов показывает их значения прямо в таблице. Для объекта класса String из предыдущего примера значение
ГЛАВА 8 Улучшенные приемы для неуправляемого кода с использованием WinDBG |
367 |
|
|
m_stringLength, равное 37, показывает количество символов в строке. Как вы сей! час увидите в полях членов объекта поле Value содержит экземпляр объекта, а вы можете дать команду !dumpobj, чтобы увидеть это значение.
Строки, ограниченные знаками >> и << показывают экземпляр домена и поло! жение в домене статического поля перед знаком >>. Если бы в EXCEPTAPP.EXE содержалось несколько доменов приложения, вы бы увидели сведения о двух до! менах и значениях для статического поля WhitespaceChars.
Теперь, когда я осветил некоторые основные команды, я хочу связать их вме! сте и показать, как с их помощью искать полезную информацию. Так как программа EXCEPTAPP.EXE остановлена WinDBG в результате возникшего исключения, было бы хорошо увидеть, какая исключительная ситуация возникла и что содержат некоторые поля, в результате чего можно было бы узнать, почему EXCEPTAPP.EXE остановилась.
Из команды !threads мы знаем, что первый поток в настоящее время исполня! ет исключительную ситуацию System.ArgumentException. Приглядевшись к выводу команд !clrstack или !dumpstack, вы заметите, что нет никаких локальных пере! менных или параметров, для которых был бы указан тип System.ArgumentException. Хорошие новости в том, что хорошая команда показывает все объекты, находя! щиеся в настоящее время в стеке текущего потока:
0:000> !dumpstackobjects |
|
||
ESP/REG |
Object |
Name |
|
ebx |
04a45670 |
System.String |
Tommy can you see me? Can you see me? |
0012f50c |
04a45f64 |
System.ArgumentException |
|
0012f524 |
04a45f64 |
System.ArgumentException |
|
0012f538 |
04a45f64 |
System.ArgumentException |
|
0012f558 |
04a44bc4 |
System.String |
Reh = |
0012f55c |
04a45f64 |
System.ArgumentException |
|
0012f560 |
04a45670 |
System.String |
Tommy can you see me? Can you see me? |
0012f564 |
04a4431c |
System.Byte[] |
|
0012f568 |
04a43a58 |
System.IO.__ConsoleStream |
|
0012f5a0 |
04a45f64 |
System.ArgumentException |
|
|
|
|
|
Так как !dumpstackobjects бродит по стеку вверх, вы увидите некоторые элементы много раз, так как они передаются как параметры ко многим функциям. В преды! дущей распечатке вы могли увидеть несколько объектов System.ArgumentException, но, посмотрев на значение объекта рядом с каждым объектом, вы заметите, что все они ссылаются на один и тот же экземпляр объекта 0x04A45F64.
Чтобы увидеть объект System.ArgumentException я использую команду !dumpobj. Я перенес колонку Name на следующую строку, чтобы все поместилось на одной странице.
0:000> !dumpobj 04a45f64
Name: System.ArgumentException
MethodTable 0x79b87b84
EEClass 0x79b87c0c
Size 68(0x44) bytes
mdToken: 02000038 (e:\winnt\microsoft.net\framework\v1.1.4322\mscorlib.dll)
368 |
ЧАСТЬ II |
Производительная отладка |
|
|
||
|
|
|
|
|
|
|
FieldDesc*: 79b87c70 |
|
|
|
|
|
|
MT |
Field |
Offset |
Type |
Attr |
Value |
Name |
79b7fcd4 |
400001d |
4 |
CLASS |
instance |
00000000 |
_className |
79b7fcd4 |
400001e |
8 |
CLASS |
instance |
00000000 |
|
|
|
|
|
|
_exceptionMethod |
|
79b7fcd4 |
400001f |
c |
CLASS |
instance |
00000000 |
|
|
|
|
|
|
_exceptionMethodString |
|
79b7fcd4 |
4000020 |
10 |
CLASS |
instance |
04a456cc |
_message |
79b7fcd4 |
4000021 |
14 |
CLASS |
instance |
00000000 |
|
|
|
|
|
|
|
_innerException |
79b7fcd4 |
4000022 |
18 |
CLASS |
instance |
00000000 |
_helpURL |
79b7fcd4 |
4000023 |
1c |
CLASS |
instance |
00000000 |
_stackTrace |
79b7fcd4 |
4000024 |
20 |
CLASS |
instance |
00000000 |
|
|
|
|
|
|
_stackTraceString |
|
79b7fcd4 |
4000025 |
24 |
CLASS |
instance |
00000000 |
|
|
|
|
|
|
_remoteStackTraceString |
|
79b7fcd4 |
4000026 |
2c |
System.Int32 |
instance |
0 |
|
|
|
|
|
|
_remoteStackIndex |
|
79b7fcd4 |
4000027 |
30 |
System.Int32 |
instance |
2147024809 _HResult |
|
79b7fcd4 |
4000028 |
28 |
CLASS |
instance |
00000000 |
_source |
79b7fcd4 |
4000029 |
34 |
System.Int32 |
instance |
0 |
_xptrs |
79b7fcd4 |
400002a |
38 |
System.Int32 |
instance |
532459699 _xcode |
|
79b87b84 |
40000d7 |
3c |
CLASS |
instance |
04a45708 |
m_paramName |
Важным свойством в исключении является Message. Так как я не могу вызвать метод прямо из WinDBG, чтобы увидеть это значение, я взгляну на поле _message, так как это и есть то место, где свойство Message хранит реальную строку. Так как поле _message помечено как CLASS, то шестнадцатеричное число в столбце Value является экземпляром объекта. Чтобы увидеть этот объект, я выполню еще одну команду !dumpobj, чтобы просмотреть его. Как мы видим, объект String имеет спе! циальное поле, поэтому мы можем видеть его действительное значение, которое выворачивается в безобидное «Thowing an exception».
0:000> !dumpobj 04a456cc |
|
|
|
|
||
Name: System.String |
|
|
|
|
|
|
MethodTable 0x79b7daf0 |
|
|
|
|
||
EEClass 0x79b7de3c |
|
|
|
|
|
|
Size 60(0x3c) bytes |
|
|
|
|
|
|
mdToken: 0200000f |
(e:\winnt\microsoft.net\framework\v1.1.4322\mscorlib.dll) |
|||||
String: Thowing an exception |
|
|
|
|||
FieldDesc*: 79b7dea0 |
|
|
|
|
||
MT |
Field |
Offset |
Type |
Attr |
Value |
Name |
79b7daf0 |
4000013 |
4 |
System.Int32 |
instance |
21 |
m_arrayLength |
79b7daf0 |
4000014 |
8 |
System.Int32 |
instance |
20 |
m_stringLength |
79b7daf0 |
4000015 |
c |
System.Char |
instance |
54 |
m_firstChar |
79b7daf0 |
4000016 |
0 |
CLASS |
shared |
static |
Empty |
>> Domain:Value 00158298:04a412f8 << |
|
|
|
|||
79b7daf0 |
4000017 |
4 |
CLASS |
shared |
static |
WhitespaceChars |
>> Domain:Value 00158298:04a4130c << |
|
|
|
ГЛАВА 8 Улучшенные приемы для неуправляемого кода с использованием WinDBG |
369 |
|
|
Резюме
Моя цель была показать мощь WinDBG и помочь вам преодолеть препятствия, которые вы встретите на своем пути. Если я еще недостаточно говорил об этом, позвольте повторить, что вам действительно необходимо читать документацию WinDBG.
Самый большой фокус в WinDBG — настройка символов и пути к исходным текстам, а также при отладке дампа, настройка пути к образу исполняемого фай! ла. WinDBG потрясающе гибок, позволяя управлять поиском символов и источ! ника их загрузки.
В дополнение к возможности отлаживать несколько процессов одновремен! но WinDBG предлагает средства управления точками прерывания, так что вы можете остановиться точно там и тогда, где и когда пожелаете. Способность исполнять команды как в точках прерывания, так и в исключительных ситуациях, дает ис! ключительную возможность отслеживать самые трудные ошибки. Команды рас! ширения помогают увидеть внутри процессов то, что невозможно было видеть раньше.
Одна из самых важных причин применения WinDBG — управление дампами. Хотя Visual Studio .NET предлагает читать файлы дампов, но это применимо толь! ко для дампов, созданных на машинах разработчиков. WinDBG — инструмент, позволяющий читать реальные файлы дампов, полученных от заказчиков.
Наконец, я надеюсь, что смог предоставить вам стартовые позиции для исполь! зования интереснейшей библиотеки расширения SOS, поддерживающей отладку
.NET. Как ни крути, это единственный способ отладить приложения, в которых скомбинированы управляемый и неуправляемый код. Вам, конечно, понадобится время на то, чтобы полностью освоить SOS. Кроме того, чтение «Production Debug! ging for .NET Framework Applications» необходимо для понимания трудностей, которые таят огромные сверхмощные приложения.

Ч А С Т Ь I I I
МОЩНЫЕ СРЕДСТВА И МЕТОДЫ ОТЛАДКИ ПРИЛОЖЕНИЙ .NET