Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Роббинс Д. - Отладка приложений для Microsoft .NET и Microsoft Windows - 2004

.pdf
Скачиваний:
321
Добавлен:
13.08.2013
Размер:
3.3 Mб
Скачать

ГЛАВА 6 Улучшенная отладка приложений .NET в среде Visual Studio .NET

221

 

 

Автоматическое развертывание собственных типов

Если вы когда то занимались отладкой управляемого кода, то, возможно, замети ли, что определенные типы выводят в окно Watch больше информации, чем дру гие. Так, при исключении типа System.ArgumentException в столбец Value окна Watch всегда выводится связанное с исключением сообщение, в то время как при исклю чении типа System.Threading.Thread выводится только тип. В первом случае вы можете быстро получить важную информацию о классе, тогда как во втором вам нужно развернуть класс и искать специфическую информацию, например имя, среди огромного списка полей членов. Я считаю, что, если и в столбце Value, и в стол бце Type окна Watch выводится одно и то же значение, пользы от этого мало. На рис. 6 2 показан пример типа, который отчаянно нуждается в авторазвертывании.

Рис. 6 2. Необходимость авторазвертывания

Добавив в окно Watch собственные типы, а также ключевые классы библиоте ки .NET Framework, которых еще там нет, вы сэкономите много времени благода ря быстрому получению нужной информации. Самое лучшее в развертывании то, что оно применяется также к подсказкам для данных, появляющимся при пере мещении курсора над перемеными в окнах исходного кода, а также при выводе параметров в окно Call Stack (стек вызовов).

Авторазвертывание очень полезно, однако оно неидеально. Самый серьезный его недостаток в том, что авторазвертывание поддерживается только в C#, J# и Managed Extensions for C++ (управляемые расширения для C++). Как и отсутствие комментариев XML в Visual Basic .NET, невозможность авторазвертывания довольно сильно огорчает, потому что это делает отладку кода Visual Basic .NET сложнее, чем она могла бы быть. Кроме того, файл правил авторазвертывания при запуске Visual Studio .NET имеет доступ только для чтения, поэтому при добавлении в него правил авторазвертывания и их тестировании вам придется поработать. Интересно, что в случае авторазвертываний для неуправляемого кода, про которые я расска жу в главе 7, файл правил читается в начале каждого сеанса отладки. Еще одна небольшая проблема: файл, содержащий правила развертывания, хранится не в каталоге проекта, а в установочном каталоге Visual Studio .NET. Это значит, что при сохранении копии файла авторазвертываний своей группы в системе управления версиями вам придется жестко задавать путь к рабочему каталогу, чтобы отлад чик мог найти его.

Первый шаг к получению всей мощи авторазвертываний заключается в нахож дении соответствующих файлов правил. Эти файлы (MCEE_CS.DAT для C#, VJSEE.DAT для J# и MCEE_MC.DAT для Managed Extensions for C++) находятся в подкаталоге <установочный каталог Visual Studio .NET >\COMMON7\PACKAGES\DEBUGGER. Изучив эти три файла, вы обнаружите, что в файле для C# несколько больше раз вертываний, чем в файле для Managed Extensions for C++ (файл для J# содержит больше развертываний, специфических для Java). Чтобы получить дополнитель

222 ЧАСТЬ II Производительная отладка

ные правила авторазвертывания при работе над проектом Managed Extensions for C++, возможно, стоит скопировать их из файла MCEE_CS.DAT в MCEE_MC.DAT.

Комментарии в начале обоих файлов, разделенные точками с запятой, описы вают операции развертывания типов C# и Managed Extensions for C++. Хотя доку ментация путем умолчания подразумевает, что в правилах авторазвертывания могут применяться только значения действительных полей, на самом деле из правил можно вызывать аксессоры чтения свойств, а также методы. Конечно, стоит убе диться в том, что метод или свойство, которые вы используете, возвращают что то, что действительно стоит возвращать, например строку или число. При возвра щении классов или сложных типов значений вы не увидите никакой полезной информации — только тип. Как обычно, я должен предупредить вас об опаснос ти применения свойств и методов, способных вызвать побочные эффекты.

В качестве примера я добавлю авторазвертывание C# для типов класса Sys tem.Threading.Thread, чтобы, если имя потока задано, его можно было видеть в столбце Value. Изучая примеры, которые Microsoft приводит в файле MCEE_CS.DAT, вы за метите, что большинство типов специфицированы полными ограничителями пространств имен. Так как в скудной документации, находящейся в начале файла MCEE_CS.DAT, о требованиях к пространствам имен ничего не говорится, для из бежания любых проблем я всегда использую полное имя типа.

Документация в файле MCEE_CS.DAT представлена в форме Бэкуса Наура (Bakus Naur form, BNR), которая далеко не всегда легка для понимания. Чтобы вам было легче, я приведу более ясный и здравый формат правил авторазвертывания: «<ty pe>=[text]<member/method,format>... Значение каждого поля объясняется в табл. 6 1. Для элемента type и раздела member/method,format угловые скобки обязательны. За метьте также, что при авторазвертывании одному элементу type могут соответство вать несколько компонентов данных (полей member).

Табл. 6-1. Записи авторазвертывания в MCEE_CS.DAT и MCEE_MC.DAT

Поле

Описание

type

Имя типа, которое должно быть полным типом.

text

Любой текст. Обычно в этом поле указывается имя компонента

 

данных или его сокращенный вариант.

member/method

Отображаемый компонент данных или вызываемый метод. В дан

 

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

 

выведено вычисленное значение. Также допускаются операторы

 

приведения типов.

format

Дополнительные спецификаторы формата переменных для их вы

 

вода в той или иной системе счисления. Разрешены значения d (де

 

сятичная с/с), o (восьмеричная с/с) и h (шестнадцатеричная с/с).

 

 

Например, при развертывании класса System.Threading.Thread меня интересует свойство Name, поэтому я должен поместить в файл такую запись:

<System.Threading.Thread>=Name=<Name>

Результат этого развертывания в окне Watch см. на рис. 6 3. На рис. 6 4 вы заме тите еще более приятный факт: в подсказках также отображаются авторазверты вания. На CD, прилагаемом к книге, вы найдете мой файл MCEE_CS.DAT, включа

ГЛАВА 6 Улучшенная отладка приложений .NET в среде Visual Studio .NET

223

 

 

ющий полезные авторазвертывания, про которые, как я думаю, программисты Microsoft просто забыли, например, развертывание класса StringBuilder. Вы мо жете использовать его в качестве основы для создания собственных файлов авто развертываний.

Рис. 6 3. Радость от авторазвертываний

Рис. 6 4. Восторг от авторазвертываний

Стандартный вопрос отладки

Есть ли способ, позволяющий увидеть в окне отладчика поток выполнения управляемого приложения?

Совместную работу компонентов программы иногда лучше всего изучать с помощью иерархии вызовов. Отладчик Visual Studio .NET не обеспечивает такой возможности (может, пока кто то не напишет соответствующий мо дуль надстройки), но зато это можно сделать, применив CORDBG.EXE, от ладчик из состава .NET Framework (о способе наблюдения за потоком вы полнения без помощи отладчика см. главу 11). Если вы желаете познать все радости отладки, какой она была примерно в 1985 году, консольный отладчик CORDBG.EXE — то, что вам нужно.

CORDBG.EXE поддерживает команду wt, аналогичную командам Watch и Trace отладчика WinDBG. Она не только показывает полную иерархию вы зовов, но и число машинных команд, выполняемых в результате вызова каж дого метода. Используя wt, лучше всего устанавливать точку прерывания на первой строке метода, с которого вы хотите начать трассировку. Програм ма будет выполняться, пока не будет достигнута команда возвращения из метода, в котором была установлена точка прерывания.

Ниже приведен вывод, полученный в результате применения wt для при ложения, которое вызывает три пустых функции (программа WT.CS с CD, прилагаемого к книге). Как вы можете представить, в результате вызова какого либо метода из библиотеки классов .NET Framework может быть выведен просто огромный текст.

(cordbg) wt

1App::Main

3App::Foo

3App::Bar

5App::Baz

3App::Bar

см. след. стр.

224 ЧАСТЬ II Производительная отладка

3App::Foo

3App::Main 21 instructions total

Если вы только начинаете работать с CORDBG.EXE, самой важной коман дой для вас будет ?, потому что она выводит справочную информацию о других командах. Указав после ? интересующую вас команду, вы получите подробную информацию о ней, а также примеры ее использования.

Советы и хитрости

Прежде чем перейти к ILDASM и промежуточному языку Microsoft (MSIL), я хочу рассказать о некоторых трюках, которые могут пригодиться при работе с управ ляемым кодом.

DebuggerStepThroughAttribute и DebuggerHiddenAttribute

Есть два очень интересных атрибута, демонстрирующих реальную силу програм мирования на основе атрибутов в .NET: DebuggerStepThroughAttribute и Debugger HiddenAttribute. Они могут применяться к свойствам, методам и конструкторам, но CLR никогда их не использует. Тем не менее отладчик Visual Studio .NET исполь зует их в период выполнения для контроля пошагового исполнения программы. Запомните: если вы будете неосторожны, эти атрибуты могут сделать отладку кода очень сложной (если не невозможной), так что используйте их на свой страх и риск. Я вас предупредил!

Более полезным является атрибут DebuggerStepThroughAttribute. Когда он при меняется к классам, структурам, конструкторам или методам, отладчик Visual Studio

.NET автоматически «перешагивает» через них, даже если вы используете коман ду Step Into (шаг внутрь). Однако вы можете задавать точки прерывания в элементах программы, которые желаете отладить. Этот атрибут лучше всего использовать в элементах, содержащих только одну строку кода, таких как аксессоры чтения и записи. Вы также увидите, что этот атрибут применяется в случае метода Initialize Component; в код, создаваемый при помощи Visual Basic .NET Windows Forms Desig ner, он включается автоматически. Возможно, вам следует задействовать его в методе InitializeComponent программ Windows Forms, написанных на C#, J# или Managed Extensions for C++.

DebuggerStepThroughAttribute по крайней мере позволяет устанавливать точки прерывания, тогда как DebuggerHiddenAttribute скрывает метод или свойство, к которым он применен, и не позволяет устанавливать точки прерывания в этом методе или свойстве. Я настоятельно рекомендую не использовать этот атрибут, потому что иначе вы не сможете отлаживать соответствующую часть кода. Одна ко он может оказаться полезным для полного сокрытия внутренних методов. DebuggerHiddenAttribute не является простым антиотладочным приемом, так как разработчики отладчика сами решают, читать ли метаданные для атрибута. На момент написания книги отладчик DBGCLR.EXE для Visual Studio .NET и .NET Framework SDK поддерживает этот атрибут, а CORDBG.EXE — нет.

ГЛАВА 6 Улучшенная отладка приложений .NET в среде Visual Studio .NET

225

 

 

Отладка в смешанном режиме

Отладка на уровне исходного кода неуправляемой DLL, вызванной управляемым приложением, называется отладкой в смешанном режиме (mixed mode debugging). Для начала нужно выяснить, как этот режим включить. Команды для приложений C# см. на рис. 6 5, а для приложений Visual Basic .NET — на рис. 6 6. Но я никак не возьму в толк, почему для C# и Visual Basic .NET понадобились две абсолютно разные страницы свойств, если все ключи командной строки для компиляторов, а также большинство команд по сути идентичны.

Рис. 6 5. Включение отладки в смешанном режиме для проекта C#

Рис. 6 6. Включение отладки в смешанном режиме для проекта Visual Basic .NET

Самый большой недостаток отладки в смешанном режиме в том, что иногда она может быть очень медленной. Управляемый и неуправляемый код лучше все го отлаживать по отдельности всегда, когда это возможно. Однако, если отладки в смешанном режиме избежать не удается, сначала нужно отключить вычисление свойств (рис. 6 7), потому что замедление связано главным образом с вычисле нием значений, выводимых в окна Watch. После отключения вычисления свойств

226 ЧАСТЬ II Производительная отладка

отладка в смешанном режиме все равно будет медленней, чем отладка только управляемого или неуправляемого кода, но все же ускорится. Большое различие между отладкой управляемого кода и отладкой в смешанном режиме состоит в том, что при отладке в смешанном режиме вы можете увидеть все модули, загружае мые управляемым процессом, если щелкните правой кнопкой в окне Modules (мо дули) и выберете пункт Show Modules For All Programs (показывать модули для всех программ).

Рис. 6 7. Отключение вычисления свойств

Отладка в смешанном режиме имеет и менее существенные недостатки. Во первых, хотя вы и отлаживаете процесс в неуправляемом режиме, вы не можете устанавливать точки прерывания по данным (см. главу 7). Во вторых, вы не мо жете создавать минидампы процесса, если отладчик не находится в неуправляе мой функции.

Удаленная отладка

Microsoft вполне заслужила Нобелевскую премию мира за то, что помогла достичь согласия двум из самых непримиримых групп в истории: разработчикам и сете вым администраторам. До управляемых приложений ситуация была такова, что разработчики должны были входить в группу Administrators на любом компьюте ре, который собирались использовать для отладки приложений. Однако, если про граммистам нужно было выполнять отладку на главном сервере (production server), сетевые администраторы очень неохотно шли на это, так как боялись изменения конфигурации системы, что, например, могло потребовать изменения паролей всех пользователей и применения паролей, состоящих из 65 символов. Со мной этого не случалось, но я слышал, что другие умудрялись сделать и такое.

Процесс, который всех примирил, называется удаленной отладкой. Я не буду излагать здесь всю соответствующую документацию, а только проясню некоторые вопросы, связанные с настройкой и применением отладчиков для работы в уда ленном режиме. Прежде всего я хочу сказать, что для удаленной отладки не надо

ГЛАВА 6 Улучшенная отладка приложений .NET в среде Visual Studio .NET

227

 

 

устанавливать на удаленном компьютере Visual Studio .NET полностью; для этого нужны только компоненты удаленной отладки из состава Visual Studio .NET. Уста новить их можно, щелкнув ссылку «Remote Components Setup» (установка удален ных компонентов) в нижней части окна приложения Visual Studio .NET Setup (рис. 6 8). Следуйте указаниям в появившемся окне под пунктом Full Remote Debugging Support (полная поддержка удаленной отладки) и установите .NET Framework до нажатия на кнопку Install Full (установить все). Забыть про установку .NET Frame work SDK очень просто, и, если такое произойдет, вы будете долго чесать голову, удивляясь невозможности отладки или запуска любых управляемых приложений. Кроме того, вам следует знать, что, хотя для удаленной отладки вовсе не требует ся входить в группу Administrators, для установки компонентов удаленной отлад ки быть членом этой группы все таки нужно.

Рис. 6 8. Установка только компонентов удаленной отладки Visual Studio .NET

Ключ к удаленной отладке — добавление вашей учетной записи в группу Debug ger Users (Пользователи отладчика) на удаленном компьютере. Конечно, чтобы иметь право добавлять пользователей в эту группу, нужно быть на соответствую щем компьютере членом группы Administrators. Наиболее частая проблема при настройке удаленной отладки заключается в том, что разработчики забывают добавить на удаленном компьютере учетную запись в группу Debugger Users.

Стандартный вопрос отладки

При отладке Web-сервисов XML я получаю исключения, утверждающие, что время операции истекло. Что делать?

При отладке Web сервисов XML эта ошибка встречается очень часто. Ука жите бесконечный лимит времени, присвоив в своем коде или в окне Watch значение –1 свойству TimeOut объекта Web сервиса XML.

228 ЧАСТЬ II Производительная отладка

ILDASM и промежуточный язык Microsoft

Несколько лет назад, начав изучать .NET, я написал классическую программу «Hello World!» и сразу захотел узнать все детали ее работы. Я испытал настоящий шок, когда понял, что .NET — по сути абсолютно новая среда разработки! При изуче нии новой среды мне нравится опускаться до простейших операций и постепен но подниматься вверх, узнавая детали совместной работы всех элементов.

Так, когда я переходил с MS DOS на Microsoft Windows 3.0 (ого, неужели я так стар?)

имне было что то непонятно, я всегда обращался к выполняемому процессором языку ассемблера. Ассемблер (который также иногда называют недвусмысленным языком) хорош тем, что он никогда не лжет. Я спокойно продолжал пользоваться этим мето дом, пока не начал переход на .NET, и мой мир перевернулся. Я потерял свою ассемб лерную опору! Я мог видеть в отладчиках ассемблер Intel, но это почти не помогало. Я видел много ассемблерных команд, вызываемых путем выделенных адресов и дру гих сложных методик, но однозначного отображения, присутствовавшего при раз работке программ Win32 на Microsoft C/C++, более не было.

Однако сразу же после написания «Hello World!» я обнаружил в .NET одну наи полезнейшую вещь: дизассемблер промежуточного языка Microsoft (ILDASM). Во оружившись им, я наконец почувствовал, что могу приступить к изучению .NET по одному элементу за раз. ILDASM позволяет увидеть язык псевдоассемблера для

.NET, называемый промежуточным языком Microsoft (MSIL). Возможно, вы никог да ничего не напишете на MSIL, но в знании ассемблера среды разработки как раз

изаключается разница между использованием среды и ее пониманием. Кроме того, хотя документация к .NET и великолепна, нет лучшего способа обучения, чем видеть реализацию приложения.

Прежде чем мы перейдем к ILDASM и MSIL, я хочу пролить свет на один рас пространенный вопрос о .NET, который часто вызывает путаницу. Мне часто го ворили, что .NET нельзя воспринимать всерьез, поскольку написанные для .NET программы очень легко поддаются восстановлению алгоритма (reverse engineering), или декомпиляции, не обеспечивая защиту интеллектуальной собственности. Это абсолютно верно. В обмен на достоинства по настоящему распределенных объек тов, сбора мусора и простоты разработки двоичные файлы .NET должны быть самоописательными. Однако приведенный аргумент ошибочен.

Такие же жалобы высказывались, когда на сцене появился язык Java. Многие поражались тому, что его так просто декомпилировать. Одна сторонняя компа ния выпустила просто великолепный декомпилятор двоичных файлов Java. Я раз говаривал с некоторыми клиентами этой компании, которым результаты деком пиляции нравились настолько, что они компилировали код своих коллег и тут же декомпилировали его, потому что в результате получался улучшенный и более понятный код! В самом начале все эти люди также очень беспокоились по пово ду интеллектуальной собственности, однако это беспокойство нисколько не за медлило признание Java корпоративными разработчиками.

Программисты, создающие Web приложения или Web сервисы XML, могут не беспокоиться о восстановлении алгоритма, потому что клиенты и пользователи не имеют физического доступа к двоичным файлам. Однако многие из вас разра батывают приложения Windows Forms или консольные приложения, и в этом случае волнение вполне резонно. С Visual Studio .NET 2003 корпорация Microsoft начала

ГЛАВА 6 Улучшенная отладка приложений .NET в среде Visual Studio .NET

229

 

 

обеспечивать разработчиков «облегченной версией» (community edition) обфус катора Dotfuscator от компании PreEmptive Solutions. Как мне кажется, все, что делает эта версия, заключается в простом переименовании классов и методов, однако и этого вполне хватает. Будьте готовы к тому, чтобы потратить на освое ние Dotfuscator некоторое время, потому что его графический пользовательский интерфейс требует основательного исследования.

Для тех, кого волнует интеллектуальная собственность приложений Windows Forms или консольных приложений, Уайз Аул1 [также известный как Брент Рек тор (Brent Rector), мой коллега по работе в Wintellect] написал отличный обфус катор для .NET — Demeanor. Demeanor обеспечивает полную защиту интеллекту альной собственности. Этот инструмент избавит вас от волнений, связанных с внедрением приложений .NET в тех случаях, когда кто то имеет физический дос туп к двоичным файлам. Подробнее о Demeanor для .NET см. по адресу: http:// www.wiseowl.com.

Если вы собираетесь выполнить обфускацию своего кода для .NET, убедитесь, что он полностью отлажен и протестирован. На данный момент нет способа со поставить код, выданный обфускатором, с исходными файлами, поэтому отлажи вать его можно только на уровне ассемблера x86.

Начинаем работу с ILDASM

ILDASM расположен в подкаталоге <установочный каталог Visual Studio .NET >\SDK\v1.1\Bin, который по умолчанию может быть не указан в переменной сре ды PATH. Выполнив файл VSVARS.BAT, находящийся в подкаталоге <установочный каталог Visual Studio .NET >\Common7\Tools, вы зададите соответствующие зна чения всем нужным переменным среды .NET и сможете получать доступ к любым утилитам .NET из командной строки. Когда вы запустите ILDASM и выберете файл для дизассемблирования, его окно будет выглядеть, как на рис. 6 9. То, что вы ви дите, — это расширения метаданных для модуля. На рис. 6 9 показаны все воз

Рис. 6 9. Основное окно ILDASM

1Wise Owl — мудрый сыч (англ.). — Прим. перев.

230 ЧАСТЬ II Производительная отладка

можные значки для типов, однако рисунок ничего не говорит о том, для чего эти значки нужны и каковы их текстовые значения при сохранении дерева в файл. Чтобы вам было легче понять это, я создал табл. 6 2.

Табл. 6-2. Описание элементов дерева ILDASM

Значок Текстовый вывод

Описание

[MOD] — заголовок

Информационные директивы, объявления классов

модуля

и данные из декларации

[NSP]

Пространство имен

[CLS]

Класс

[INT]

Интерфейс

[ENU]

Перечисление

[VCL]

Размерный класс

[MET]

Экземплярный метод (закрытый, открытый

 

или защищенный)

[STM]

Статический метод

[FLD]

Экземплярное поле (закрытое, открытое

 

или защищенное); также сборка

[STF]

Статическое поле

[EVT]

Событие

[PTY]

Свойство (получение и/или задание свойства)

 

 

Если вам нужна более подробная информация и статистика об открываемых файлах, запустите ILDASM с ключом командной строки /ADV. Это включит вывод расширенной информации и добавит в меню View три новых пункта.

COR Header (заголовок COR) позволяет просмотреть информацию, содержа щуюся в заголовке файла.

Statistics (статистика) выводит различную статистику о процентном соотно шении и категориях всех метаданных в системе.

MetaInfo (метаинформация) содержит подменю, позволяющее выбрать, какую именно информацию вы желаете получить. Чтобы увидеть эту информацию, выберите в подменю пункт Show! (показать) (или нажмите Ctrl+M), и она по явится в отдельном окне MetaInfo. Если не выбрать конкретной информации, при выборе пункта Show! будет выведен просто дамп метаданных.

Если для конкретного модуля у вас есть исходный код, вам непременно захо чется отметить в меню View пункт Show Source Lines (показать исходный код). Для показа исходного кода можно также задать в командной строке ключ /SOURCE. В результате этого дизассемблер будет выводить исходный код программы в виде

Соседние файлы в предмете Программирование на C++