в которой Windows 98 превосходит
Есть одна область, связанная с отладкой, в которой Windows 98 превосходит Windows 2000. Речь идет о журналах программы Dr. Watson. В Windows 98 эти журналы содержат гораздо больше информации, особенно о процессах, выполняющихся в системе, и о версии каждого модуля. С помощью этой информации намного легче дублировать состояние машины при ее тестировании.
Большая часть аварийной информации, регистрируемой в журнале программы Dr. Watson, одинакова для этих операционных систем, но в Windows 98 ее намного больше. Например, программа Dr. Watson из Windows 98 дизассемблирует каждый элемент в стеке вызовов. Чтобы пояснить дополнительную информацию, с которой вы можете встретиться в журнале программы Dr. Watson, рассмотрим секцию Details этого журнала.
Верхняя часть секции Details выглядит так:
*———> Details <———*
Command line: "g:\Dev\Book\CD\SourceCode\Output\WDBG.exe"
Trap Oe 0000 - Invalid page fault
eax=00000000 ebx=0065fba6 есх=ООЬ938ЬО edx=fffdcla5 esi=005301c0
edi=0065fae4
eip=0040bd2d esp=0065f908 ebp=0065f934 — — — nv up El pi nz na PE nc
cs=0167 ss=016f ds=016f es=016f fs=38d7 gs=382f
WDBG.EXE:.text+0xad2d:
>0167:0040bd2d 8b4804 mov ecx,dword ptr [eax+04]
В начале секции показана полная командная строка, за которой следует описание ошибки, похожее на описание исключения в Windows 2000. После описания ошибки выводится секция регистров (в том же формате, что и в Windows 2000), а за ней — команда, которая вызвала сбой.
Далее Windows 98 выводит часть своего 16-разрядного "наследия" — таблицу сегментных регистров, где показаны значения соответствующих селекторов. Дополнительную информацию можно получить в руководствах по процессорам Intel.
sel type base lim/bot
---- ---- ------ --------
cs 0167 r-x- 00000000 ffffffff
ss 016f rw-e 00000000 OOOOd7aO
Первая секция журнала выглядит так:
Первая секция журнала выглядит так:
Microsoft (R) Windows 2000 (ТМ) Version 5.00 DrWtsn32
Copyright (С) 1985-1999 Microsoft Corp. All rights reserved.
Application exception occurred:
App: (pid=252)
When: 9/4/1999 @ 16:43:56.173
Exception number: cOOOOOOS (access violation)
Информация заголовка сообщает причину аварийного останова. В данном случае — это исключительная ситуация (исключение), возникшая в приложении. Номера исключений для некоторых аварийных ситуаций невозможно перевести в удобочитаемое описание, например, такое, как показано в последней строке нашего заголовка ("access violation — нарушение доступа" для исключения с (шестнадцатеричным) номером С0000005). Все возможные значения номеров исключений можно найти в препроцессорных директивах #define STATUS_ файла WINNT.H. Значения, отмеченные в документации, как данные типа EXCEPTION_, возвращает функция GetExceptionCode, но реальные величины находятся в директивах #define STATUS_. Функция GetExceptionCode преобразует номер исключения в ЕХСЕРТION_-значение, а по ее документации можно найти более подробное описание данного сбоя.
Секция system information (сведения о системе) самоочевидна и не требует пояснений:
* - - -> System Information < - - -*
Computer Name: PLATO
User Name: John
Number of Processors: 1
Processor Type: x86 Family 6 Model 6 Stepping 10
Windows 2000 Version: 5.0
Current Build: 2128
Service Pack: None
Current Type: Uniprocessor Free
Registered Organization: Enter your company name here
Registered Owner: John Robbins
Секция Task List (список задач) выглядит примерно так:
* - - - > Task List < - - -*
0 Idle.ёхе
8 System.exe
132 smss.exe
160 csrss.exe
156 winlogon.exe
208 services.exe
220 lsass.exe
364 svchost.exe
424 svchost.exe
472 spoolsv.exe
504 MWMDMSVC.exe
528 MWSSW32.exe
576 regsvc.exe
592 MSTask.exe
836 Explorer.exe
904 tp4mon.exe
912 tphkmgr.exe
920 4nt.exe
940 taskmgr.exe
956 tponscr.exe
268 msdev.exe
252 WDBG.exe
828 NOTEPAD.exe
416 drwtsn32.exe
0 _Total.exe
В этой секции показан список процессов, которые выполнялись во время сбоя. К сожалению, Windows 2000 не показывает информацию о версиях, включенных в этот список файлов, поэтому в случае необходимости нужно получить эту информацию у пользователя. Числа слева от имен программных файлов — это десятичные идентификаторы процессов (PID — Program ID).
Следующий список содержит адреса загрузки всех модулей, находившихся в адресном пространстве во время аварии:
(00400000 - 0042D000) D:\Dev\Book\CD\SourceCode\Output\WDBG.pdb
(77F80000 - 77FF9000) E:\WINNT\symbols\dll\ntdll.dbg
(60000000 - 6001А000) D:\Dev\Book\CD\SourceCode\Output\BugslayerUtil.pdb
(77Е80000 - 77F35000) E:\WINNT\symbols\dll\kernel32.dbg
(77Е10000 - 77Е74000) E:\WINNT\symbols\dll\user32.dbg
(77F40000 - 77F7C000) E:\WINNT\symbols\dll\gdi32.dbg
(72950000 - 72967000) E:\WINNT\symbols\dll\dbghelp.dbg
(78000000 - 78046000)
• (77DB0000 - 77Е07000) Е:\WINNT\symbols\dll\advapi32.dbg
(77D30000 - 77DA2000) E:\WINNT\symbols\dll\rpcrt4.dbg
(10200000 - 10264000)
(63100000 - 63108000) D:\Dev\Book\CD\SourceCode\Output\LocalAssist.pdb
(62000000 - 6202В000) D:\Dev\Book\CD\SourceCode\Output\i386CPUHelp.pdb
(63000000 - 63010000) D:\Dev\Book\CD\SourceCode\Output\LocalDebug.pdb
(5F400000 - 5F4E5000)
(77ВЗ0000 - 77ВВА000) E:\WINNT\symbols\dll\comctl32.dbg
(775А0000 - 777DE000) E:\WINNT\symbols\dll\shell32.dbg
(77С50000 - 77С9А000) E:\WlNNT\symbols\dll\shlwapi.dbg
(76В20000 - 76В5Е000) E:\WINNT\syitibols\dll\comdlg32.dbg
(77АЗ0000 - 77В24000) E:\WINNT\symbols\dll\ole32.dbg
(77990000 - 77А24000) E:\WINNT\symbols\dll\oleaut32.dbg
(77СА0000 - 77D25000)
(77850000 - 7788В000)
(770В0000 - 770D3000)
(6В6Е0000 - 6B6FC000) E:\WINNT\symbols\dll\msdbi.dbg
(68ED0000 - 68EDB000) E:\WINNT\symbols\dll\psapi.dbg
Числа в круглых скобках в левой части этого списка указывают начальный и максимальный адреса загрузки каждого модуля. Намного полезнее было бы показать в этой секции фактические имена модулей, загруженных в адресное пространство. К сожалению, как видно по именам, расположенным справа от адресов загрузки, здесь показаны только каталоги, в которые Dr. Watson загрузил файлы отладочных символов соответствующего модуля. Незаполненные входы означают, что никакой отладочной информации для данного модуля загружено не было.
Можно только догадываться, какие модули были загружены по указанным адресам. Как уже не раз говорилось, жизненно необходимо знать адреса загрузки библиотек динамической компоновки (DLL) в адресном пространстве процесса. Чтобы найти информацию о DLL на пользовательских машинах, можно написать небольшую утилиту, которая будет просматривать DLL-файлы и сообщать их имена, адреса загрузки и размеры.
Ниже показана первая часть дампа состояния потока (с идентификационным номером Ox2fc):
State Dump for Thread Id 0x2fс
eax=00000000 ebx=7ffdfOOO ecx=008c67cO edx=0000033c esi=00134c78 edi=0012fd74
eip=0040bd2d esp=0012fb98 ebp=0012fbc4 iopl=0 nv up ei pi nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
function: CWDBGProjDoc::HandleBreakpoint
0040bdll push esi
0040bdl2 push edi
0040bdl3 mov eax,Oxcccccccc
0040bdl8 mov [ebp+OxeO],eax ss:00b4dl9a=????????
0040bdlb mov [ebp+0xe4],eax ss:00b4dl9a=????????
0040bdle mov [ebp+0xe8],eax ss:00b4dl9a=????????
0040bd21 mov [ebp+Oxec],eax ss:00b4dl9a=????????
0040bd24 mov [ebp+Oxf0],eax ss:00b4dl9a=????????
0040bd27 mov [ebp+OxeO],ecx ss:00b4dl9a=????????
0040bd2a mov eax,[ebp+Oxc] ss:00b4dl9a=????????
FAULT ->004Obd2d mov ecx,[eax+0x4] ds:00ald5d6=????????
0040bd30 cmp dword ptr [ecx],0x80000003 ds:008c67cO=0041b714
0040bd36 jz CArray<COneShotBP,COneShotBP>::SetSize+Ox25d (0041485d)
0040bd38 mov esi,esp
0040bd3a push 0x382
0040bd3f push 0x420030
0040bd44 push 0x420064
0040bd49 push 0x0
0040bd4b call dword ptr [_imp_DiagAssertA (00423ad4)]
0040bd51 cmp esi,esp
0040bd53 call _chkesp (00416b5a)
0040bd58 test eax,eax
В журнале показан дамп состояния каждого потока программы на момент сбоя. Он содержит всю информацию, которая нужна пользователю для того, чтобы определить, как и почему произошел сбой.
В регистровой части дампа показано содержимое всех регистров во время сбоя. Важно следить за регистром EIP (указателем машинных команд). В данном примере используются отладочные символы, так что можно видеть, какую функцию выполнял этот поток во время сбоя, однако довольно часто журналы этой программы не могут пользоваться отладочными символами1. Нет ничего страшного, если в журнале нет имени функции. В этом случае нужно загрузить для своего приложения проект программы CrashFinder, рассмотренной в главе 8, нажать клавиши <Ctrl>+<F> и ввести в открывшееся диалоговое окно Find EIP-адрес этого потока.
Тогда вместо имени функции в журнале указывается значение <nosymbols>. — Пер.
Так уж случилось, что сбой произошел в этом потоке. Единственным индикатором этого события в журнале является указатель FAULT-> в середине кода дизассемблера. Иногда этот указатель не выводится. Тогда, для того чтобы определить, что происходило с потоком во время сбоя, нужно просмотреть (по журналу) состояние каждого потока и ввести соответствующий EIP-адрес в CrashFinder.
Код дизассемблера рассмотрен в главе 6. Новыми элементами являются значения, показанные справа от команд. Дизассемблер программы Dr. Watson пытается найти самый эффективный адрес для ссылки на команду. Справа от команды можно увидеть, с каким еще адресным значением работала команда. Метка ss: указывает на адреса сегмента стека, а ds: — на адреса сегмента данных.
Единственный эффективный адрес в коде дизассемблера, который с гарантией является корректным, — это адрес в указателе команд. Другие адреса могут быть некорректны, потому что значение, на которое ссылается команда, может быть изменено.
Например, пусть первая команда, дизассемблированная в дампе состояния потока, использовала (в качестве аргумента) ссылку на ячейку памяти из регистра ЕВХ. Если сбой дала команда, расположенная на 10 инструкций позже, то одна из промежуточных команд может легко изменить содержимое ЕВХ. Однако когда Dr. Watson выполняет дизассемблирование, то для эффективного преобразования адреса он использует текущее значение ЕВХ (т. е. то, которое этот регистр содержал во время сбоя). По этой причине эффективный адрес, показанный в коде дизассемблера дампа состояния потока, может быть неправильным. Для того чтобы убедиться, что в дампах журнала отображены корректные адреса, тщательно проверьте, не могли ли какие-нибудь команды, предшествующие сбою, изменить значения регистров.
Можно вычислить, что в данном потоке произошел сбой, потому что команда:
Ox0040BD2D MOV ECX,[ЕАХ+Ох4]
пыталась получить доступ к ПУСТОМУ (NULL) указателю в ЕАХ (ЕАХ=00000000). Посмотрев внимательно на команду в предшествующей строке:
MOV ЕАХ, [ЕВР+ОхС],
можно предположить, что с положительным смещением от ЕВР, вероятно, расположена адресная ссылка на параметр функции. Величина смещения (ОхС) означает, что команда сослалась на второй параметр функции. Первой гипотезой при отладке этого сбоя должна быть такая: выполнение функции завершилось неудачей, потому что ей был передан неправильный второй параметр (все это показывает, как важно хорошо знать язык ассемблера для чтения журналов программы Dr. Watson!).
Ниже показана вторая часть дампа состояния потока, которая названа stack Back Trace (обратная трассировка стека) (). Заметьте, что длинные значения столбца Function Name (и только они) там, где они не поместились в строке, перенесены на следующую строку.
*——> Stack Back Trace <——*
FramePtr ReturnAd Paramtl Param#2 Param#3 Param#4 Function Name
0012FBC4 0040BCB5 0000033C 00000000 80000003 008C67CO
!CWDBGProj Doc::HandleBreakpoint
0012FBEO 00405A9C 0000033C 010DFCOC 008C68BO 0012FCF4
!CWDBGProj Doc::HandleExceptionEvent
0012FBF4 5F42F3AC 0000033C 010DFCOC 0012FD74 00134C78
!CDocNotifyWnd::HandleExceptionEvent
0012FCF4 5F42ECE8 00000502 0000033C 010DFCOC 0012FD10 !0rdinal4118 0012FD14 5F42C889 00000502 0000033C 010DFCOC 77F86-618 !0rdinal5076 0012FD88 5F42CD25 008C68BO 000602A4 00000502 0000033C !0rdinall045 0012FDB4 5F4905FD 000602A4 00000502 0000033C 010DFCOC !0rdinalll92 0012FDE4 77E135F8 000602A4 00000502 0000033C 010DFCOC !0rdinalll93 0012FE04 77E15FE8 5F4905B3 000602A4 00000502 0000033C
user32!UserCallWinProc
0012FE20 77E1600E 004A9B70 00000502 0000033C 010DFCOC
user32!DispatchClientMessage (FPO: Non-FPO
[5,1,0])
0012FE48 77F9D8B7 0012FE58 00000018 004A9B70 00000502
user32!_fnDWORD (FPO: Non-FPO [1,4,0])
0012FE68 77E15FB5 77E17BD9 00422250 00000000 00000000
ntdlliKiUserCallbackDiSpatcher (FPO: [0,0,0])
0012FE90 5F4396F8 00422250 00000000 00000000 00000000
user32!DispatchClientMessage (FPO: Non-FPO [5,1,0])
0012FEB8 5F438E1D 77F86618 77F81A9B 7FFDFOOO 00000001 !0rdinal4239 0012FEDC 5F439AD4 00422218 0012FF08 5F43366E 77F86618 !0rdinal4409 0012FEE8 5F43366E 77F86618 77F81A9B 7FFDFOOO 00422218 !0rdinal4408 0012FF08 00417028 00400000 00000000 00133A73 00000001 !Ordinalll90 0012FF20 00416E53 00400000 00000000 00133A73 00000001 'WinMain 0012FFCO 77E9BC52 77F86618 77F81A9B 7FFDFOOO C0000005 !WinMainCRTStartup
0012FFFO 00000000 00416CAO 00000000 OOOOOOC8 00000100
kernel32!BaseProcessStart (FPO: Non-FPO [1,8,3])
Данный пример журнала использует отладочные символы (вследствие чего в колонке Function Name отображены имена всех вызванных к моменту сбоя функций), однако, в пользовательском журнале этого, вероятно, не будет1. В колонке ReturnAd перечисляются адреса возврата функций, находящихся в стеке вызовов. Если журнал пользователя не содержит отладочных символов, то нужно загрузить каждый адрес из колонки ReturnAd в программу CrashFinder (чтобы вычислить последовательность вызовов функций, которая привела к сбою).
Тогда вместо имени функции в журнале указывается значение <nosymbols>. — Пер.
Колонки Paramtl, #2, #3 и #4 показывают четыре первых возможных параметра функций в стеке вызовов. При высоко оптимизированном выпуском построении и без отладочных символов показанные здесь значения, вероятно, некорректны. Однако их можно использовать в качестве отправной точки для ручной прокрутки кода.
Имена функций показаны в формате <модуль>! «функциях Функции с именами ! Ordinal#N являются функциями порядкового экспорта. Если у вас нет исходного кода DLL, которая выполняет экспорт функций по порядковым номерам (а не по именам), то вам просто не повезло. Однако, вследствие того, что библиотека классов MFC (Microsoft Foundation Classes) поставляется с исходными кодами, порядковые значения MFC-функций найти можно. Например, для программы WDBG известно, что библиотека MFC42D.DLL загружается по адресу Ox5F400000, так что есть возможность отыскать порядковые номера ее функций, потому что все MFC-функции экспортируются по своим порядковым номерам через DEF-файл компоновщика.
Существует одно предварительное условие для преобразования порядковых номеров MFC-функций в их имена: необходимо точно знать версию MFC DLL на аварийной машине. На моей машине, называемой \\PLATO, имелась MFC42D.DLL из системы Visual C++ 6 Service Pack 3.
Ниже приводится последовательность действий для преобразования порядковых номеров функций в их имена:
1. Откройте каталог \VC98\MFC\SRC\Intel системы Visual C++.
2. Выберите подходящий DEF-файл для того MFC-файла, который собираетесь посмотреть. Например, DEF-файлом для MFC42D.DLL является MFC42D.DEF.
3. Ищите порядковый номер. Чтобы найти имя функции с порядковым номером Ordinal4118 из предыдущего стека, я поискал бы в файле MFC42D.DEF строку с номером 4118. Она выглядит так:
? OnWndMsg@CWnd@@MAEHIIJPAJ @Z 4118 NONAME.
Имя, расположенное слева от подстроки "@ 4118 NONAME", является расширенным (декорированным) именем функции, экспортируемой по порядковому номеру. Чтобы преобразовать декорированное имя в обычное, используйте программу UNDNAME.EXE, которая поставляется в составе набора инструментальных средств Platform SDK. Для функции с порядковым номером 4118, обычно, именем функции является CWND::OnWndMsg.
Третья, заключительная часть дампа состояния потока называется Raw stack Dump (дамп необработанного стека) и выглядит так:
*———> Raw Stack Dump <———*
0012fb98 74 fd 12 00 78 4c 13 00-00 fO fd 7f cO 67 8c 00 t...xL....g..
0012fba8 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc ................
0012fbb8 e8 fc 12 00 2e 8a 41 00-ff ff ff ff eO fb 12 00 .....A......
0012fbc8 b5 be. 40 00 3c 03 00 00-00 00 00 00 03 00 00 80 ..@.<.......
0012fbd8 cO 67 8c 00 cc cc cc cc-f4 fb 12 00 9c 5a 40 00 .g........Z@.
0012fbe8 3c 03 00 00 Oc fc Od 01-bO 68 8c 00 f4 fc 12 00 <......h.....
0012fbf8 ac f3 42 5f 3c 03 00 00-Oc fc Od 01 74 fd 12 00 ..B_<....t...
0012fc08, 78 4c 13 00 00 fO fd 7f-09 00 00 00 bO 68 8c 00 xL.......h..
0012fcl8 04 00 00 00 00 00 00 00-00 00 8c 00 50 00 8c 00 .........P...
0012fc28 50 00 8c 00 01 00 00 00-ae 05 12 00 70 2d 00 00 P........p-..
0012fc38 01 00 00 00 fa 00 00 00-8c fc 12 00 8b 48 fb 77 ..........H.w
0012fc48 00 00 8c 00 00 00 9f 01-01 00 00 00 80 fc 12 00 ............
0012fc58 7c fc 12 00 84 fc 12 00-00 00 00 00 00 00 00 00 | ...........
0012fc68 00 00 8c 00 00 00 8c 00-90 fc 12 00 d5 19 49 5f ...........I_
0012fc78 04 00 00 00 18 66 f8 77-9b la f8 77 a4 fc 12 00 ...f.w...w...
0012fc88 d5 19 49 5f 04 00 00 00-18 66 f8 77 9b la f8 77 ..!_...f.w..w
0012fc98 00 fO fd 7f 48 el 4c 5f-48 4d 13 00 cc fc 12 00 ....H.L_HM...
0012fca8 45 16 49 5f cc fc 12 00-d5 19 49 5f d4 fc 12 00 E.I_...I_....
0012fcb8 d.8- fc 12 00 d5 19 49 5f-04 00 00 00 18 66 f8 77 ... I_.. f.
0012fcc8 50 22 42 00 00 00 00 00-Oa 00 00 00 00 a5 41 00 P"B........A.
Я редко просматриваю эту информацию. Однако если бы я действительно увяз в проблеме сбоя, то можно было бы начать просмотр с приблизительного определения значений некоторых локальных переменных. Жирным шрифтом выделены два адреса возврата, которые я смог разгадать при просмотре этого дампа.
CPU и аппаратные средства
П Andrew S. Tanenbaum.Structured Computer Organization. — 4th ed., Prentice-Hall, 1998
Превосходное введение в архитектуру компьютера. Эта книга заполнена информацией, которой я пользуюсь для решения каждодневных проблем отладки. Книга содержит некоторые типографские и технические ошибки, но если вы сумеете обойти их, то получите удовлетворение от ее чтения.
Справочные руководства по Intel CPUIntel свободно (бесплатно) распространяет руководства для своих процессоров. Если вы выполняете серьезную отладку, то эти руководства чрезвычайно полезны и информативны. PDF-файлы компании Adobe можно загрузить с узла компании Intel:
developer.intel.com/design/litcentr/index.htm
Hans-Peter Messmer. The Indispensable PC Hardware Book. — 3rd ed., Addison-Wesley, 1997Самое удачное обсуждение аппаратных средств PC. Эта книга бесценна, когда необходимо организовать взаимодействие с аппаратными средствами PC.
Инструментальные средства
В разговоре о программных инструментах, я не могу оставаться сторонним наблюдателем. Во-первых, в течение четырех лет я работал в NuMega и входил в команды, которые разрабатывали некоторые из ведущих рыночных программных инструментов. Во-вторых, я все время их использую. Приведенный ниже список поставщиков этих программ предоставлен исключительно для ссылок и не означает поддержки какой-либо компании или продукта. Перечисленные инструменты связаны с отладкой и автоматизированным тестированием.
Компания Compuware NuMega (www.numega.com)• BoundsChecker
Автоматическое обнаружение ошибок времени выполнения и диагностика для программ на языках Visual C++, Borland Delphi и Borland C++ Builder (для всех типов операционных систем Windows).
• TraeTime
Автоматический анализ производительности для программ на языках Visual C++, Visual Basic и Java (для всех типов операционных систем Windows).
• TrueCoverage
Автоматический анализ покрытия кода для программ на языках Visual C++, Visual Basic и Java (для всех типов операционных систем Windows).
• CodeReview
Автоматический анализ исходного кода для программ на языках Visual C++, Visual Basic и Java (для всех типов операционных систем Windows).
• SmartCheck
Автоматическое обнаружение ошибок времени выполнения и диагностика для программ на языках Visual C++, Visual Basic и Java (для всех типов операционных систем Windows).
FailSafeАвтоматическая обработка ошибок и восстановление для программ на языкeVisual Basic (для всех типов операционных систем Windows).
• JCheck
Визуальный анализ потоков и событий для программ на языке Java (для всех типов операционных систем Windows).
• SoftICE
Усовершенствованный отладчик Windows для отладки программ как в пользовательском режиме, так и в режиме ядра для всех типов операционных систем Windows.
Компания Rational Software (www.rational.com)• Purify
Автоматическое обнаружение ошибок времени выполнения и диагностика для Visual С++-программ (только для Windows NT и Windows 2000).
• PureCoverage
Автоматический анализ покрытия кода для программ на языках Visual C++, Visual Basic и Java (только для Windows NT и Windows 2000).
• Quantify
Автоматический анализ производительности для программ на языках Visual C++, Visual Basic и Java (только для Windows NT и Windows 2000).
• Rational Robot
Инструмент регрессивного тестирования для всех типов операционных систем Windows.
• Visual Test
Инструмент регрессивного тестирования для всех типов операционных систем Windows.
• Компания Mutek Software (www.mutek.com)
• BugTrapper
Перехват ошибки и "посмертная" отладка для программ на языках Visual C++ и Visual Basic (для всех типов операционных систем Windows).
Языки
Brian W. Kernighan and Dennis Ritchie.The С Programming Languag. — 2nd ed., Prentice Hall, 1988 (Есть перевод: Керниган Б., Ритчи Д., Фьюэр А.Язык программирования СИ. — М., Финансы и статистика, 1985. —Пер.)
Эта книга является наиболее полным руководством по программированию на С и прекрасно написанной технической книгой, лучшей из всех, которые я когда-либо читал.
Neill Graham.Learning C++. — McGraw-Hill, 1991Я использовал эту книгу при изучении C++. В отличие от других объемных книг по C++ она написана коротко, в хорошем стиле и точно.
The Mandelbrot Set.Advanced Microsoft Visual Basic 6.0. — 2nd ed., Microsoft Press, 1998Превосходная книга по Visual Basic, которая освещает многие реальные проблемы. Первую главу —"On Error GoTo Hell" Пита Морриса, и шестую —"Оставаясь под контролем" Марка Пирса должны читать все программисты на Visual Basic.
Mark Nelson. C++Programmer's Guide to the Standard Template Library. — IDG Books, 1995Мое отношение к библиотеке стандартных шаблонов (Standard Template Library — STL) весьма неоднозначно. К счастью, в книге Нельсона приводится много примеров и пояснений наиболее ярких моментов использования этой библиотеки.
Книги
Всю мою карьеру разработчика и отладчика программного обеспечения меня сопровождали следующие книги, которые я настоятельно рекомендую и вам.
Отладка и тестирование
Brian Kernighan and Rob Pike. The Practice of Programming. — Addison-Wesley, 1999
В этой книге приводится замечательное обсуждение разработки, отладки и тестирования программ.
Steve Maguire.Writing Solid Code. — Microsoft Press, 1993Книга посвящена, главным образом, программированию на языке С, содержит превосходные советы по определениям интерфейса и обходу неприятных проблем языка.
Rex Black.Managing the Testing Process. — Microsoft Press, 1999Для того чтобы лучше разрабатывать программы, нужно знать, как улучшить их тестирование. Эта превосходная книга поможет вам улучшить методику разработки и способ взаимодействия со специалистами по контролю качества.
Jonathan В. Rosenberg.How Debuggers Work. — John Wiley & Sons, 1996Эта книга — превосходное введение в работу отладчиков и проблемы их проектирования.
Разработка программного обеспечения
Steve McConnell.Code Complete. — Microsoft Press, 1993
Это лучшая книга по конструированию программного обеспечения, которую я когда-либо читал. Каждый разработчик должен иметь собственный экземпляр этой книги и читать его от корки до корки каждый год.
Steve McConnell.Rapid Development. — Microsoft Press, 1996Эта книга научила меня, как нужно управлять командой разработчиков и планированием проектов.
Steve Maguire.Debugging the Development Process. — Microsoft Press, 1994Эта книга является введением в методики, с помощью которых компания Microsoft разрабатывает программное обеспечение. Из-за того что компания Microsoft — наиболее успешная программистская компания на планете, она должна все делать правильно. Вы можете многому научиться из этой книги.
Jim McCarthy.Dynamics of Software Development. — Microsoft Press, 1995Здесь изложен очень интересный взгляд на разработку программного обеспечения (с точки зрения менеджера) — с прослеживанием графиков поставки больших программных продуктов. Правила, которые предлагает Джим Маккарти превосходны, потому что они все исходят из практического опыта, а не только из академического теоретизирования.
Web-сайты
В моей папке \Favorites обозревателя Microsoft Internet Explorer только три сайта для разработчиков:
MSDN Online (msdn.microsoft.com)MSDN — это первое место, куда нужно обращаться за информацией по Windows. К MSDN Online можно обращаться как по этому адресу, так и через поддерживаемые компанией Microsoft журналыMicrosoft Systems Journal (MSJ) иMicrosoft Internet Developer (MIND). Имейте в виду, что MSDN — полумаркетинговая организация, поэтому в ее материалах иногда встречается навязчивая реклама.
Sysinternals (http:// www.sysinternals.com/)Марк Руссинович (Mark Russinovich) и Брюс Когсвелл (Bryce Cogswell) владеют одним из лучших наборов отладочных утилит, включая Regmon, Filemon, DebugView HandleEx и много других. Многие утилиты приходят с полными исходными текстами и все бесплатны! Я проверяю этот сайт по крайней мере один раз в неделю.
MVPS.org (www.mvps.org)Это Web-сайт участников сетевой телеконференции, называющих себя Most Valuable Professional (MVP) newsgroup. MVP — это разработчики и пользователи, которые являются экспертами в специфических областях и помогают различным группам новостей отвечать на вопросы по технологиям и программным продуктам компании Microsoft.
Вот некоторые другие сайты, которые могут вас заинтересовать:
CodeGuru (www.codeguru.com)Информационный сайт, посвященный преимущественно системе программирования Visual C++.
Experts Exchange (www.experts-exchange.com)Технический информационный обменный сайт, который охватывает многие тематические разделы Windows.
Dr. Dobb's Journal Microprocessor Resources (www.x86.org)Здесь можно найти все, что нужно знать о семействе процессоров х86
. Архивы различных почтовых адресатов (discuss.microsoft.com/archives)Архивы некоторых полезных почтовых адресатов, таких как ATL и DCOM.
Windows и Windows-технологии
Charles Petzold.Programming Windows. — 5th ed., Microsoft Press, 1999
Одна эта книга научит вас всему, что нужно знать о работе Windows-программ, причем на самом высоком уровне. Многие проблемы можно решить только в том случае, если хорошо понимать, как обрабатываются сообщения, как работает интерфейс графических устройств (Graphics Device Interface — GDI) и другие объекты на уровне SDK.
Jeffrey Richter.Programming Applications for Microsoft Windows. — 4th ed., Microsoft Press, 1999Эта книга охватывает все важнейшие аспекты разработки \¥т32-при-ложений. Главы по DLL, потокам, синхронизации и структурированной обработке исключений — наилучшие из доступных описаний, и все они имеют прямое отношение к более быстрой и эффективной отладке ваших программ.
Jeff Prosise.Programming Windows with MFC. — 2nd ed., Microsoft Press, 1999Эта книга — наиболее полное руководство по программированию с использованием библиотеки классов MFC. Если вы используете MFC, то должны иметь эту книгу.
Paul Dilascia.Windows++. — Addison-Wesley, 1992В отличие от многих книг по проектированию, здесь приводится сильная и жизнеспособная библиотека С++-классов для Windows.
Don Box.Essential COM. — Addison-Wesley, 1998В окне Disassembly, COM'-интерфейс является просто указателем на массив указателей, что позволяет легко понять смысл СОМ-модели. СОМ-модель, однако, гораздо сложнее простого указателя. Она играет фундаментальную роль в программировании, так что если вы хотите иметь шанс корректно разрабатывать и отлаживать свои программы, то должны понимать, как эта модель работает. Книга Бокса может послужить хорошим началом на пути изучения СОМ-технологии.
COM — Component Object Model, модель компонентных объектов. —Пер.
David A. Solomon.Inside Windows NT. — 2nd ed., Microsoft Press, 1998В этой книге представлен широкий официальный обзор ядра Windows NT. Хотя она непосредственно адресована тем, кто пишет драйверы устройств, вам она поможет уловить смысл того, как совмещаются различные части этой операционной системы.
Matt Pietrek.Windows 95 System Programming Secrets. — IDG Books, 1995Эта книга не переиздавалась, но нужно постараться найти ее копию. При попытке отладить что-то большее, чем простое нарушение доступа в Windows 95/98, вы испытываете чувство глубокого разочарования главным образом потому, что Windows 95/98 являются гибридными 16/32-разрядными операционными системами. Однако многие разделы книги, такие как глава о переносимом исполняемом (Portable Executable — РЕ) формате файлов, применимы также и к Windows 2000.
Brent Rector and Chris Sells.ATI Internals. — Addison-Wesley, 1999Библиотека активных шаблонов (ATL) помогает строить самые компактные и самые быстрые СОМ-объекты. Эту книгу нужно иметь для того, чтобы полностью использовать все возможности ATL.
Модификаторы позиционных точек прерывания
После установки регулярной позиционной точки прерывания можно уточнить (модифицировать) способ прерывания в этой точке. Чтобы установить условие модификации, нужно выделить позиционную точку прерывания в диалоговом окне Breakpoints и нажать кнопку Condition, чтобы открыть диалоговое окно Breakpoint Condition.
Тип модификатора и его вид в окнеBreakpoints |
Описание |
Счетчик пропусков at '{,WINMAIN.CPP} .24, ' skip five times (5)' |
Пропустить указанное число точек прерывания. Ввести в редактируемое поле Enter The Number Of Times To Skip Before Stopping число пропускаемых точек прерывания. Установив в счетчике пропусков число, превосходящее максимальное количество итераций цикла, можно узнать, сколько раз сработала точка прерывания перед сбоем в цикле. После сбоя в цикле откройте окно Breakpoints — количество пропусков будет выведено в нижней части окна |
Выполнить прерывание, когда условное выражение примет значение TRUE. at 4,WINMAIN.CPP} .24, when Ч=°=3' |
Ввести оцениваемое выражение в поле Enter The Expression To Be Evaluated. Выражение не должно содержать вызовов функций или макросов. Допускаются операции сравнения в стиле языка С. При проверке строчных значений проверяйте отдельные символы, связав их операциями AND |
Выполнить прерывание, когда изменится значение переменной at MfWINMAIN.CPP) .24, when %szBuffer' (length: 5) changes |
Ввести идентификатор переменной в поле Enter The Expression To Be Evaluated. Для массивов или структур ввести число элементов в поле Enter The Number Of Elements To Watch In Array Or Structure. Размер элемента базируется на размере введенной переменной. Прерывания будут вызывать только те записи данных, которые изменяют переменную |
Позиционные точки прерывания
Все позиционные точки прерывания (location breakpoints) устанавливаются вручную в редактируемом поле Break at на вкладке Location диалогового окна Breakpoints.
Тип позиционной точки и ее вид в окнеBreakpoints |
Описание |
Исходная строка at M/TEST.CPP,} .20' |
Нажать кнопку Insert/Remove breakpoint, когда курсор установлен на строке исходного кода, на которой нужно вызвать прерывание |
Первая инструкция в функции at 'Cdialog: :0n0k' |
Ввести имя функции. Если отладчик выполняется, он может подсказать подходящее имя в диалоговом окне Resolve Ambiguity |
Любой адрес at '0x417013' |
Ввести шестнадцатеричный адрес, на котором нужно выполнить прерывание |
Прерывание на экспортируемой системной функции (отладочные символы модуля загружены) at '{, ,KERNEL32.DLL} _LoadLibraryA@4' |
Ввести контекстную информацию и вставить информацию двоичного модуля. Для экспортируемой функции ввести имя с символом подчеркивания, знаком @ и числом параметров, умноженным на 4 |
Прерывание на экспортируемой системной функции (отладочные символы модуля не загружены)at {, , KERNEL32 . DLL}_LoadLibraryA' |
Ввести контекстную информацию, вставить информацию двоичного модуля и ввести экспортируемое имя |
Точки прерывания глобальных выражений и условные точки прерывания
Точки прерывания этого типа (global expression and conditional breakpoints) устанавливаются в поле Enter the expression to be evaluated на вкладке Data диалогового окна Breakpoints. Они используют отладочные регистры Intel CPU. Хотя таких регистров четыре, можно устанавливать только две точки данного типа. При этом лучше использовать шестнадцатеричные адреса, приведенные к типам short, word или double word. Отладчик принимает такую точку, но у него почему-либо может отсутствовать доступ к отладочному регистру (тогда он перейдет в пошаговый режим, проверяя адреса памяти на каждой ассемблерной команде).
Тип модификатора и его вид в окнеBreakpoints |
Описание |
Глобальное выражение at y*(char*)Ox4287C8' |
Точка прерывания (ТП) этого типа срабатывает при изменении содержимого памяти по указанному адресу |
Глобальное выражение at '*(char*)Ox4287C8=='G" |
ТП этого типа срабатывает при записи определенного значения (например, символа 'G', см. слева) по указанному адресу |
Точки прерывания сообщений
Точки прерывания сообщений (message breakpoints) особенно полезны при программировании в среде SDK. При работе с библиотекой классов MFC очень полезна установка такой точки на общей для всех процессов функции AfxWndProc. Можно также применять позиционную ТП с модификатором в виде условного выражения. Например, чтобы получить прерывание на сообщении WM_PAINT для конкретного класса, нужно ввести выражение
{,WINCORE.CPP,}.1584 when (this==Ox0012EFE74)&&(message==OxF)