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

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

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

ГЛАВА 2 Приступаем к отладке

41

 

 

При работе над неуправляемым кодом рассматривайте предупреждения как ошибки (в большинстве случаев)

По сравнению с управляемым кодом неуправляемый код C++ не только позволя ет вам при компиляции выстрелить себе в ногу2 , но и дает заряженный пистолет со взведенным курком. В C++ предупреждение на самом деле означает, что ком пилятор делает предположение по поводу намерений программиста. В качестве прекрасного примера можно привести такое предупреждение, как C4244 [‘conver sion’ conversion from ‘type1’ to ‘type2’, possible loss of data (Преобразование ‘con version’ из ‘type1’ в ‘type2’ может привести к потере данных)], которое всегда воз никает при преобразовании знакового типа в беззнаковый и наоборот. В данном случае имеется только 50% шансов, что компилятор прочитает ваши мысли и правильно решит, что ему нужно сделать со старшим битом.

Очень часто исправление подобной ошибки тривиально: достаточно, напри мер, выполнить явное приведение типа переменной. Общая идея в том, чтобы сделать код как можно менее неопределенным, чтобы компилятор не был вынужден делать какие либо предположения. Некоторые из предупреждений просто неза менимы для прояснения кода. Таким является, например, предупреждение C4101 (‘identifier’: unreferenced local variable), сообщающее, что локальная переменная нигде не используется. Исправление этого предупреждения облегчит проведение обзоров кода и сделает программу гораздо понятнее для программистов, которые будут ее сопровождать: никто не будет тратить время на выяснение того, для чего же нужна эта дополнительная переменная и где она используется. Другие предуп реждения, такие как C4700 [local variable ‘name’ used without having been initialized (локальная переменная ‘name’ используется, не будучи инициализированной)], ука зывают на точное место ошибки. Мне известны случаи, когда простое повыше ние уровня диагностики и исправление появившихся предупреждений приводи ло к исчезновению ошибок, на поиск которых могли бы уйти недели.

Проекты Visual C++, создаваемые при помощи мастеров, имеют по умолчанию уровень диагностики 3, что соответствует в CL.EXE ключу /W3. Еще выше уровень 4, /W4, а ключ /WX позволяет даже сделать так, чтобы все предупреждения рассмат ривались компилятором как ошибки. Для задания уровня диагностики откройте окно Property Pages, папку C/C++ и выберите страницу свойств General. В поле Warning Level (уровень диагностики) укажите значение Level 4 (/W4). Двумя стро ками ниже находится поле Treat Warnings As Errors, в котором следует задать зна чение Yes (/WX). Правильные значения обоих полей см. на рис. 2 3.

Я с радостью заявил бы, что компиляцию всегда следует выполнять на уровне диагностики 4 и все предупреждения нужно считать ошибками, однако реальность не позволяет мне сделать это. Входящая в состав Visual C++ библиотека стандар тных шаблонов (Standard Template Library, STL) имеет много недоработок, не по зволяющих работать с ней на уровне диагностики 4. Компилятор также имеет несколько проблем с шаблонами. К счастью, эти проблемы поддаются решению.

2По английски: «shoot yourself in the foot». Вероятно, автор обыгрывает название изве стной книги: Allen I. Holub. Enough Rope to Shoot Yourself in the Foot: Rules for C and C++ Programming. — McGraw Hill, 1995. — Прим. перев.

42 ЧАСТЬ I Сущность отладки

Вы можете подумать, что достаточно задать уровень диагностики 4 и не счи тать предупреждения ошибками, но такой подход дискредитирует саму суть опи санной идеи. Я обнаружил, что разработчики очень быстро перестают обращать внимание на предупреждения в окне Build. Если не исправлять все предупрежде ния, какими бы безобидными они ни казались, по мере их возникновения, более важные предупреждения начинают теряться в потоке вывода среди других сооб щений. Хитрость в том, чтобы более явно указывать, какие предупреждения вы желаете исправлять. Конечно, вы должны избавляться от большинства предупреж дений путем улучшения кода программы, однако можно также отключить специ фические ошибки, используя директиву #pragma warning. Кроме того, она позволяет управлять уровнем диагностики ошибок в конкретных заголовочных файлах.

Хорошим примером уместного понижения уровня диагностики может служить включение заголовочных файлов, которые не компилируются на уровне 4. Пони зить уровень диагностики можно через расширенную директиву #pragma warning, появившуюся в Visual C++ 6. В следующем фрагменте я понижаю уровень диагно стики для включения подозрительного заголовочного файла и сразу же возвра щаю ему прежнее значение, чтобы мой код компилировался на уровне 4:

#pragma warning ( push , 3 )

#include "IDoNotCompileAtWarning4.h"

#pragma warning ( pop )

Директива #pragma warning позволяет также запретить отдельные предупрежде ния. Она полезна, например, когда вы применяете безымянную структуру или объединение и получаете на уровне диагностики 4 ошибку C4201, «nonstandard extension used: nameless struct/union» (использовано нестандартное расширение: структура/объединение не имеет имени). Вот как при помощи директивы #pragma warning запретить это предупреждение (заметьте: я закомментировал свои действия и объяснил их). При запрещении отдельных предупреждений ограничивайте диапазон действия #pragma warning специфическими разделами программы. Поместив директиву на слишком высоком уровне, вы можете замаскировать другие ошиб ки своей программы.

//Я запрещаю предупреждение "nonstandard extension used: nameless struct/union",

//потому что мне не нужен машино независимый код

#pragma warning ( disable : 4201 ) struct S

{

float y; struct

{

int a ; int b ; int c ;

};

}*p_s ;

// Снова разрешаю предупреждение. #pragma warning ( default : 4201 )

ГЛАВА 2 Приступаем к отладке

43

 

 

Существует одно предупреждение, C4100 [«‘identifier’: unreferenced formal parame ter» (‘identifier’: неиспользуемый формальный параметр)], исправление которого иногда вызывает недоумение. Если у вас есть параметр, который не применяется, его, пожалуй, следует удалить из определения метода. Однако при написании программы на объектно ориентированном языке программирования можно вы полнить наследование от метода, которому, как потом оказывается, параметр не нужен, но изменять базовый класс нельзя. Вот правильный способ обработки ошибки C4100:

//Этот код сгенерирует ошибку C4100: int ProblemMethod ( int i , int j )

{

return ( 5 ) ;

}

//Правильный способ избежания ошибки C4100: int GoodMethod ( int /* i */ , int /* j */ )

{

return ( 22 ) ;

}

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

STL, поставляемая с Visual Studio .NET, сложна для понимания и отладки. Что-нибудь может мне помочь?

Я понимаю, что STL из состава Visual Studio .NET писали гораздо более ум ные люди, чем я, но даже в этом случае ее почти невозможно понять. С одной стороны, концепция STL хороша: эта библиотека широко используется и имеет согласованный интерфейс. С другой стороны, природа STL, постав ляемой с Visual Studio .NET, и шаблонов вообще такова, что при возникно вении проблемы вам придется приложить гораздо больше усилий для ее понимания, чем для отладки на уровне ассемблера.

Вместо STL из Visual Studio .NET я рекомендую свободно распространя емую STL от компании STLport (www.stlport.org). Библиотека STLport не только бесконечно понятней, но и включает гораздо лучшие средства под держки многопоточности и отладки. Учитывая эти преимущества и то, что она не налагает никаких ограничений на коммерческое использование, я настоятельно рекомендую использовать именно ее, а не STL из Visual Studio

.NET, если, конечно, вам вообще нужна STL.

Если вы не используете STL, этот способ работает прекрасно. Однако при ра боте с STL он эффективен не всегда. Применяя STL, лучше всего включать в пре компилированные заголовочные файлы только заголовочные файлы STL. Это значительно облегчает изоляцию директив #pragma warning ( push , 3 ) и #pragma warning ( pop ) в заголовочных файлах. Другое важное преимущество заключается в суще ственном ускорении компиляции. Прекомпилированный заголовочный файл представляет по сути дерево синтаксического анализа, благодаря чему позволяет сэкономить много времени, так как STL — очень объемная библиотека. Наконец, чтобы получить полный контроль над утечками и искажениями памяти при ис

44 ЧАСТЬ I Сущность отладки

пользовании стандартной библиотеки C, нужно держать заголовочные файлы STL в одном месте. О стандартной библиотеке C для отладки см. главу 17.

Основной смысл сказанного в том, что с самого начала проекта нужно выпол нять компиляцию на уровне диагностики 4 и рассматривать все предупреждения как ошибки. Когда вы впервые повысите уровень диагностики проекта, вы скорее всего будете удивлены числом появившихся предупреждений. Изучите их и ис правьте. Возможно, это приведет и к исчезновению нескольких ошибок. Если вы думаете, что заставить программу компилироваться с ключами /W4 и /WX нельзя, я могу доказать обратное: весь неуправляемый код примеров с прилагаемого к этой книге CD компилируется с обоими флагами, заданными для всех конфигураций.

Разрабатывая неуправляемый код, знайте адреса загрузки DLL

Если вы когда нибудь гуляли по лесу, то знаете: чтобы не заблудиться, очень важ но запоминать всякие примечательные объекты. Не имея ориентиров, можно просто ходить по кругу. При аварийном завершении приложения нужно иметь аналогичный ориентир, который поможет найти правильный путь и не блуждать впустую по коду своей программы в окне отладчика.

Первым важным ориентиром при крахе программы являются базовые адреса DLL или элементов управления на базе ActiveX (OCX), указывающие на область их размещения в памяти. Когда клиент предоставит вам адрес аварийного завер шения программы, вам нужно быстро определить, к какой DLL он относится, по первым двум или трем цифрам. Я не утверждаю, что вы должны знать адреса всех системных DLL, но нужно помнить хотя бы базовые адреса DLL, используемых в вашем проекте.

Если все ваши DLL будут загружаться по уникальным адресам, вы будете иметь отличные ориентиры, которые помогут искать причину проблемы. Ну, а если все ваши DLL будут иметь одинаковые адреса загрузки? Очевидно, ОС не сможет ото бразить их на одну и ту же область памяти. При загрузке DLL, желающей распо ложиться в уже занятой области памяти, ОС должна будет «переадресовать» DLL, выделив ей другое место. И как же определить, где какая DLL загружена? Увы, мы не можем узнать, как поступит ОС на разных компьютерах. А значит, при получе нии адреса аварийного завершения программы вы не будете иметь представле ния о том, откуда этот адрес взялся. В свою очередь это означает, что ваш началь ник будет очень недоволен, так как вы не сможете объяснить ему причину сбоя приложения.

Для проектов, созданных при помощи мастеров, по умолчанию справедливо следующее: библиотеки DLL элементов ActiveX, созданных в среде Visual Basic 6, загружаются по адресу 0x11000000, а DLL, написанные на Visual C++, — по адресу 0x10000000. Готов спорить, что по меньшей мере половина имеющихся на дан ный момент в мире DLL пытается загрузиться по одному из этих адресов. Изме нение адреса загрузки DLL называется модификацией базового адреса (или пе реадресацией) и является простой операцией, позволяющей задать другой адрес загрузки, отличный от используемого по умолчанию.

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

ГЛАВА 2 Приступаем к отладке

45

 

 

загрузке DLL. Первый подразумевает использование окна Modules (модули) отлад чика Visual Studio .NET. Запустите приложение в среде Visual Studio .NET и откройте окно Modules, для чего нужно выбрать меню Debug, подменю Windows или нажать CTRL+ALT+U, если комбинации клавиш настроены по умолчанию. Если базовый адрес модуля был модифицирован, его значок будет отмечен красным кружком с восклицательным знаком. Кроме того, диапазон занимаемых модулем адресов будет отмечен звездочкой. На рис. 2 7 показано окно Modules с переадресованной биб лиотекой SYMSRV.DLL во время сеанса отладки.

Рис. 2 7. Переадресованная DLL в окне Modules отладчика Visual Studio .NET

Второй способ — загрузить бесплатное приложение Process Explorer, написанное моим хорошим другом и когда то соседом Марком Руссиновичем (Mark Russinovich) из Sysinternals (www.sysinternals.com). Как следует из названия, Process Explorer позволяет узнать разнообразную информацию о процессах, например, загружен ные DLL и открытые описатели (handle). Это настолько полезный инструмент, что если у вас его еще нет, немедленно прекратите чтение и загрузите его! Кроме того, вам следует прочитать главу 14, где описаны дополнительные приемы и хитрос ти, которые могут облегчить отладку при помощи Process Explorer.

Узнать, была ли переадресована DLL, очень легко. Просто выполните описан ные ниже действия. На рис. 2 8 показано, как выглядит окно Process Explorer, если DLL процесса была переадресована.

1.Запустите Process Explorer и свой процесс.

2.Выберите в меню View пункт View DLLs.

3.Выберите в меню Options пункт Highlight Relocated DLLs (Выделить переадре сованные DLL).

4.Выберите свой процесс в верхней половине основного окна.

Все переадресованные DLL будут выделены желтым цветом.

Рис. 2 8. Переадресованные DLL в окне программы Process Explorer

46 ЧАСТЬ I Сущность отладки

Еще один отличный инструмент, показывающий переадресованные DLL не только с модифицированным, но и с исходным адресом, — программа ProcessSpy из прекрасной статьи Кристофа Назарра (Christophe Nasarre) «Escape from DLL Hell with Custom Debugging and Instrumentation Tools and Utilities, Part 2» (Избавление от ада DLL при помощи собственных отладочных инструментов и утилит, часть 2), опубликованной в журнале MSDN Magazine в августе 2002 года. По функцио нальности программы Process Explorer и ProcessSpy похожи, однако ProcessSpy поставляется с исходным кодом, так что вы можете узнать, как она колдует.

Переадресация DLL ОС не только затрудняет поиск причин краха приложения, но и замедляет его выполнение. При переадресации ОС должна прочитать инфор мацию о модификации адресов, проработать все участки программы, получаю щие доступ к DLL, и изменить их, потому что DLL будет размещена в памяти не на своем излюбленном месте. Если в приложении будет два конфликта адресов загрузки, время его запуска может увеличиться аж вдвое!

Есть и еще одна крупная проблема: переадресовав модуль, ОС не сможет выг рузить его из памяти полностью, если ей понадобится выделить место для друго го кода. Если модуль загружается по предпочитаемому адресу загрузки, ОС может выгрузить его на диск, а затем загрузить обратно. Однако, если базовый адрес модуля был модифицирован, значит, была изменена и область памяти, содержа щая код этого модуля. Поэтому ОС должна где то хранить эту память (возможно, в страничном файле), даже если модуль выгружен из памяти. Легко догадаться, что это может «съедать» большие блоки памяти и замедлять работу компьютера из за затрат на их перемещение.

Базовый адрес DLL можно модифицировать двумя способами. Первый — с помощью утилиты REBASE.EXE из состава Visual Studio .NET. REBASE.EXE имеет массу опций, но лучше всего вызывать ее из командной строки с ключом /b, указывая после него стартовый базовый адрес и названия DLL. Хочу вас обрадовать: как только вы модифицируете базовый адрес какой либо DLL, вам почти никогда больше не придется возвращаться к ней. Модифицируйте базовые адреса DLL только до ее регистрации. Если вы модифицируете базовый адрес DLL после ее регист рации, она не загрузится.

В табл. 2 1 приведен фрагмент документации Visual Studio .NET, посвященный модификации базовых адресов DLL. Как видите, рекомендуется использовать ал фавитную схему. Я обычно следую ей, потому что она проста. DLL ОС загружают ся по адресам от 0x70000000 до 0x78000000, так что следование правилам табл. 2 1 избавит вас от конфликтов с ОС. Конечно, вам всегда следует изучать адрес ное пространство своих приложений при помощи Process Explorer или ProcessSpy, чтобы узнать, не загружена ли уже какая нибудь DLL по тому адресу, который вы хотите использовать.

Если в приложение включены четыре DLL — APPLE.DLL, DUMPLING.DLL, GIN GER.DLL и GOOSEBERRIES.DLL, для правильной модификации их адресов нужно выполнить REBASE.EXE трижды. Это проиллюстрировано следующими тремя ко мандами:

REBASE /b 0x60000000 APPLE.DLL

REBASE /b 0x61000000 DUMPLING.DLL

REBASE /b 0x62000000 GINGER.DLL GOOSEBERRIES.DLL

ГЛАВА 2 Приступаем к отладке

47

 

 

Если в командной строке указать несколько DLL, как я только что поступил с биб лиотеками GINGER.DLL и GOOSEBERRIES.DLL, утилита REBASE.EXE модифициру ет их базовые адреса так, чтобы они загружались друг за другом, начиная с ука занного адреса.

Табл. 2-1. Схема модификации базовых адресов DLL

Первая буква названия DLL

Базовый адрес

A–C

0x60000000

D–F

0x61000000

G–I

0x62000000

J–L

0x63000000

M–O

0x64000000

P–R

0x65000000

S–U

0x66000000

V–X

0x67000000

Y–Z

0x68000000

 

 

Другой метод модификации базового адреса DLL — указать адрес загрузки при компоновке DLL. В Visual C++ это можно сделать, открыв окно Property Pages, папку Linker и выбрав страницу свойств Advanced (расширенные настройки). Шестнад цатеричный адрес загрузки DLL следует указать в поле Base Address (базовый адрес). Этот адрес будет передан компоновщику LINK.EXE вместе с ключом /BASE (рис. 2 9).

Утилиту REBASE.EXE позволяет автоматически задавать адреса загрузки несколь ких DLL одновременно без ограничений, но при задании адресов во время ком поновки следует быть внимательнее. Если вы укажете адреса загрузки нескольких DLL слишком близко, то в отладочном окне Module увидите, что их адреса будут модифицированы. Поэтому, чтобы никогда впоследствии не волноваться об ад ресах загрузки, их нужно задавать с достаточным интервалом.

В примере с REBASE.EXE я задал бы адреса загрузки этих DLL так:

APPLE.DLL 0x60000000

DUMPLING.DLL 0x61000000

GINGER.DLL 0x62000000

GOOSEBERRIES.DLL 0x62100000

Обратите особое внимание на библиотеки GINGER.DLL и GOOSEBERRIES.DLL, потому что их названия начинаются с одинаковой буквы. В таких случаях я за даю другой адрес загрузки при помощи третьей по старшинству цифры. Если бы я собрался использовать еще одну DLL, название которой также начиналось бы с буквы «G», я бы указал адрес загрузки 0x62200000.

Ознакомиться с проектом, в котором адреса загрузки заданы вручную, можно на примере проекта WDBG из главы 4. Я забыл сказать, что ключ /BASE позволяет указать текстовый файл, содержащий адреса загрузки всех DLL приложения. В проекте WDBG я применил именно такой способ.

Для переадресации DLL и OCX можно использовать оба метода: модифициро вать базовые адреса DLL при помощи утилиты REBASE.EXE или вручную, однако, пожалуй, лучше всего следовать второму методу и выполнять переадресацию DLL вручную. Все примеры DLL на CD, прилагаемом к этой книге, я переадресовал

48 ЧАСТЬ I Сущность отладки

вручную. Основное преимущество такого метода в том, что MAP файл будет со держать специфический заданный адрес. MAP файл — это текстовый файл, ука зывающий, по каким адресам компоновщик размещает все символы и строки программы. При заключительных компоновках MAP файлы следует создавать все гда, так как они являются единственными простыми текстовыми описаниями символов. MAP файлы окажутся особенно полезными в будущем, когда вам нуж но будет найти причину краха программы, а ваш отладчик не сможет работать со старыми символами. Если же переадресацию DLL выполнять посредством RE BASE.EXE, создаваемый компоновщиком MAP файл будет содержать первоначаль ный базовый адрес, и для его преобразования в модифицированный адрес пона добятся некоторые вычисления (о MAP файлах см. главу 12).

Рис. 2 9. Задание базового адреса DLL

Меня часто спрашивают: «Базовые адреса каких файлов модифицировать?» Следуйте простому правилу: если код написан вами или кем нибудь из вашей груп пы, модифицируйте его базовый адрес. В противном случае не трогайте его. Если вы используете компоненты сторонних фирм, вам придется располагать свои двоичные файлы в памяти, учитывая уже занятые этими компонентами области.

Как поступать с базовыми адресами управляемых модулей?

В данный момент вы, возможно, думаете, что, раз уж управляемые компоненты компилируются в DLL, их базовые адреса также следует модифицировать. Более того, если вы изучали ключи компиляторов C# и Visual Basic .NET, то, может быть, видели ключ /BASEADDRESS для задания базового адреса. Однако в случае управляе мого кода все немного не так. Если вы изучите управляемую DLL с помощью про граммы DUMPBIN.EXE из состава Visual Studio .NET, служащей для просмотра дампов файлов Portable Executable (PE), или при помощи великолепного инструмента PEDUMP, созданного Мэттом Питреком (Matt Pietrek) (MSDN Magazine, февраль 2002), вы заметите одну импортируемую функцию _CorDllMain из библиотеки MSCOREE.DLL и одно значение в таблице переадресации.

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

ГЛАВА 2 Приступаем к отладке

49

 

 

ка входа модуля, т. е. точка, с которой начинается его выполнение, оказалась рас положенной по тому же адресу, что и импортируемая функция _CorDllMain. Это подтвердило, что в модуле нет неуправляемого исполняемого кода.

В конечном счете модификация базовых адресов управляемых модулей не принесет вам такого же огромного преимущества, как в случае неуправляемого кода. Тем не менее я выполняю ее, так как мне кажется, что загрузчик ОС все таки не остается в стороне, вследствие чего переадресация управляемой DLL при заг рузке будет замедлять запуск программы. Если вы решаете модифицировать ба зовые адреса управляемых DLL, это нужно делать во время компоновки. Если мо дифицировать адрес зарегистрированной управляемой DLL при помощи REBASE.EXE, система безопасности заметит, что DLL была изменена, и откажется загружать ее.

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

Какие дополнительные параметры компилятора C# помогут мне заранее позаботиться об отладке управляемого кода?

Хотя управляемый код устраняет многие ошибки, отравлявшие нашу жизнь при работе с неуправляемым кодом, некоторые ошибки все же могут ска заться на работе вашей программы. К счастью, есть очень полезные ключи командной строки, задав которые можно облегчить обнаружение таких ошибок. Хорошая новость для любителей Visual Basic .NET: эта среда абсо лютно правильно настроена по умолчанию, поэтому вам не понадобится задавать дополнительных ключей компилятора. Если вы не желаете настра ивать компилятор вручную, модуль надстройки SettingsMaster из главы 9 сделает это за вас.

/checked+

(проверка целочисленной арифметики)

В областях потенциальных проблем можно использовать ключевое слово checked, но это нужно делать при написании кода. Ключ командной строки /checked+ позволяет включить проверку целочисленного переполнения для всей программы. Если результат окажется вне диапазона допустимых зна чений типа данных, программа автоматически сгенерирует исключение периода выполнения. Задание этого ключа приводит к небольшому увели чению объема кода, поэтому я предпочитаю оставлять его включенным в отладочных компоновках и использовать ключевое слово checked для явной проверки подобных ошибок в заключительных компоновках. Для установ ки этого ключа нужно открыть окно Property Pages, папку Configuration Properties, выбрать страницу Build и задать в поле Check For Arithmetic Overflow/ Underflow (Проверка арифметического переполнения) значение True.

/noconfig

(игнорировать файл CSC.RSP)

Интересно, но задать этот ключ в среде Visual Studio .NET невозможно. Тем не менее, если вы захотите собирать программу из командной строки, знать о его предназначении не помешает. По умолчанию, прежде чем обрабаты

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

50 ЧАСТЬ I Сущность отладки

вать командную строку, компилятор C# читает файл CSC.RSP, в котором также указаны ключи командной строки. Чтобы автоматизировать свою работу, вы можете задать в нем любые допустимые ключи. Стандартный файл CSC.RSP из состава Visual Studio .NET содержит огромное число ключей /REFERENCE для распространенных сборок, которые все мы постоянно используем. А вот для таких библиотек, как System.XML.dll, этот ключ не нужен, так как файл CSC.RSP содержит запись /r: System.XML.dll. Файл CSC.RSP находится в ката логе версии .NET Framework: <Название каталога Windows>\Micro soft.NET\Framework\<Номер версии .NET Framework>.

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

Какие дополнительные параметры компилятора и компоновщика помогут позаботиться об отладке неуправляемого кода?

Существует много ключей, способных помочь повысить производительность приложения и облегчить его отладку. Кроме того, как я уже говорил, я не совсем согласен со значениями параметров компилятора и компоновщика Visual C++ по умолчанию в проектах, создаваемых при помощи мастеров. Поэтому я всегда изменяю некоторые их параметры. Если вы не желаете делать это вручную, используйте модуль надстройки SettingsMaster из гла вы 9.

Ключи компилятора CL.EXE

Задать эти ключи вручную можно, открыв окно Property Pages, папку C/C++, страницу Command Line (командная строка) и введя их в поле Additional Options (дополнительные ключи), однако гораздо лучше указывать их в соответствующих им местах. Задание ключей командной строки в поле Additional Options может привести к проблемам, потому что разработчики не привыкли искать их в этом месте.

/EP /P

(препроцессорная обработка с выводом в файл)

В случае проблем с макрокомандами могут пригодиться ключи /EP и /P. Они приказывают препроцессору обработать исходный файл, преобразовав все макрокоманды в обычную форму и включив все указанные файлы, и сохра нить результат в файле с тем же именем, но с расширением .I. Открыв этот файл, вы сможете узнать, во что преобразуются ваши макрокоманды. Убе дитесь, что у вас хватает места на диске, потому что файлы .I могут зани мать по несколько мегабайт. Чтобы препроцессор сохранил в файле ком ментарии, нужно также указать ключ /C (не удалять комментарии).

Для задания ключей /EP и /P откройте окно Property Pages, папку C/C++, выберите страницу Preprocessor (препроцессор) и укажите в поле Generate Preprocessed File (генерировать файл, прошедший препроцессорную обра ботку) значение Without Line Numbers (/EP /P) (без номеров строк). Поле Keep Comments (сохранять комментарии), расположенное на той же стра нице, позволяет задать компилятору ключ /C. Помните, что эти ключи не

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