About the Book
The definitive guide to finding
and fixing bugs in applications for Microsoft .NET and Windows
You get huge development advantages with
Microsoft Visual Studio® .NET 2003—but you need a new bag of debugging
tricks to take full advantage of them in today’s .NET and Win32® development
worlds. Learn lethally effective, real-world application debugging techniques
for .NET Framework 1.1 and Windows with this fully updated programming
guide. Debugging expert John Robbins expands the first edition of his classic
debugging book with all-new scenarios and bug-killing tools, tips, and
techniques. You’ll see every .NET and Windows debugging scenario here—from
XML Web services and Microsoft ASP.NET to Windows services and exceptions.
Along with John’s expert guidance, you get more than 6 MB of his battle-tested
source code—for the tools and tactics you need to ship better software
faster!
Topics covered include:
• Where bugs come from and how to think
about solving them
• Debugging during coding
• Operating system debugging support and
how Win32 debuggers work
• Advanced debugger usage and .NET debugging
with Visual Studio .NET
• Advanced native code techniques with
Visual Studio .NET and WinDBG
• Extending the Visual Studio .NET integrated
development environment
• Managed exception monitoring
• Flow tracing and performance
• Finding source and line information
with just a crash address
• Crash handlers
• Debugging Windows services and DLLs
that load into services
• Multithreaded deadlocks
• Automated testing
• The Debug C run-time library
• A high-performance tracing tool for
server applications
• Smoothing the working set
• Appendixes: Reading Dr. Watson log files,
plus resources for .NET and Windows developers
CD-ROM features:
• 6+ MB of professional-level source code
samples written in Microsoft Visual C++®, Visual C#®, and Visual
Basic® .NET
• Debugging Tools for Windows
• Microsoft .NET Framework 1.1 SDK
• Windows Application Compatibility Toolkit
(ACT)
Related Books
Introducing WinFX™ The Application Programming
Interface for the Next Generation of Microsoft® Windows® Code Name
"Longhorn"
Writing Secure Code, Second Edition
Table of Contents
List of Sidebars
xix
Acknowledgments
xxi
Introduction
xxiii
PART I THE GESTALT OF DEBUGGING
1 Bugs: Where They Come From
and How You Solve Them 3
Bugs
and Debugging 3
What Are Bugs? 4
Process Bugs and Solutions 8
Planning for Debugging 18
Prerequisites
to Debugging 19
The Skill Set 19
Learning the Skill Set 21
The Debugging
Process 22
Step 1: Duplicate the Bug 24
Step 2: Describe the Bug 25
Step 3: Always Assume That the Bug Is Yours 25
Step 4: Divide and Conquer 25
Step 5: Think Creatively 26
Step 6: Leverage Tools 27
Step 7: Start Heavy Debugging 27
Step 8: Verify That the Bug Is Fixed 28
Step 9: Learn and Share 30
Final Debugging Process Secret 30
2 Getting Started Debugging
33
Track
Changes Until You Throw Away the Project 33
Version Control Systems 34
Bug Tracking Systems 38
Choosing the Right Systems for You 40
Schedule
Time for Building Debugging Systems 41
Build All Builds with Debugging Symbols 42
For Managed Code, Treat Warnings as Errors 46
For Native Code, Treat Warnings as Errors—Mostly 48
For Native Code, Know Where Your DLLs Load 52
What About Managed Modules and Base Addresses? 57
Design a Lightweight Diagnostic System for Release Builds 65
Frequent
Builds and Smoke Tests Are Mandatory 67
Frequent Builds 67
Smoke Tests 68
Build
the Installation Program Immediately 70
QA Must
Test with Debug Builds 70
Install
the Operating System Symbols and Set Up a Symbol Store 71
Your Source and Symbol Servers 81
3 Debugging During Coding
83
Assert,
Assert, Assert, and Assert 85
How and What to Assert 86
Assertions in .NET Windows Forms or Console Applications 95
Assertions in ASP.NET Applications and XML Web Services 103
Assertions in Native C++ Applications 113
Different Types of Visual C++ Assertions 118
SUPERASSERT 121
Trace,
Trace, Trace, and Trace 142
Tracing in Windows Forms and Console .NET Applications 144
Tracing in ASP.NET Applications and XML Web Services 146
Tracing in Native C++ Applications 148
Comment,
Comment, Comment, and Comment 149
Trust
Yourself, but Verify (Unit Testing) 151
PART II POWER DEBUGGING
4 Operating System Debugging
Support and How Win32 Debuggers Work 157
Types
of Windows Debuggers 159
User-Mode Debuggers 159
Kernel-Mode Debuggers 161
Windows
Operating System Support for Debuggees 164
Just-In-Time (JIT) Debugging 164
Automatically Starting in a Debugger (Image File Execution Options) 168
MinDBG:
A Simple Win32 Debugger 171
WDBG:
A Real Debugger 190
Reading and Writing Memory 192
Breakpoints and Single Stepping 195
Symbol Tables, Symbol Engines, and Stack Walking 200
Step Into, Step Over, and Step Out 209
So You
Want to Write Your Own Debugger 210
What's
Next for WDBG? 211
5 Advanced Debugger Usage with
Visual Studio .NET 213
Advanced
Breakpoints and How to Use Them 214
Breakpoint Tips 215
Quickly Breaking on Any Function 217
Location Breakpoint Modifiers 224
Multiple Breakpoints on a Single Line 227
The Watch
Window 228
Calling Methods in the Watch Window 230
The Set Next Statement Command 232
6 Advanced .NET Debugging with
Visual Studio .NET 235
Advanced
Breakpoints for .NET Programs 236
Conditional Expressions 236
The Watch
Window 241
Expanding Your Own Types Automatically 241
Tips
and Tricks 245
DebuggerStepThroughAttribute and DebuggerHiddenAttribute 245
Mixed Mode Debugging 246
Remote Debugging 247
ILDASM
and Microsoft Intermediate Language 249
Getting Started with ILDASM 251
CLR Basics 257
MSIL, Locals, and Parameter 258
The Important Instructions 259
Other Reverse Engineering Tools 266
7 Advanced Native Code Techniques
with Visual Studio .NET 269
Advanced
Breakpoints for Native Applications 269
Advanced Breakpoint Syntax 270
Breakpoints on System or Exported Functions 271
Conditional Expressions 274
Data Breakpoints 277
The Watch
Window 280
Formatting Data and Expression Evaluation 280
Timing Code in the Watch Window 283
The Undocumented Pseudoregisters 283
Expanding Your Own Types Automatically 283
Remote
Debugging 291
Tips
and Tricks 295
Debugging Injected Code 295
The Memory Window and Auto Memory Evaluation 295
Exception Monitoring 296
More Symbol Handling Tips 298
Detaching from Windows 2000 Processes 299
Handling Dump Files 299
x86 Assembly
Language 302
The Basics of the CPU 303
A Word About the Visual C++ .NET Inline Assembler 309
Instructions You Need to Know 310
Common Sequence: Function Entry and Exit 313
Calling Procedures and Returning 315
Calling Conventions 316
Variable Access: Global Variables, Parameters, and Local Variables
322
More Instructions You Need to Know 327
String Manipulation 333
Common Assembly-Language Constructs 336
Structure and Class References 338
A Complete Example 339
The Disassembly Window 341
Walking the Stack Manually 346
Tips and Tricks 349
8 Advanced Native Code Techniques
with WinDBG 353
Before
You Begin 354
The Basics
356
Debugging
Situations 360
Getting Help 361
Ensuring Correct Symbols Are Loaded 362
Processes and Threads 366
General
Debugging with the Command Window 372
Looking at and Evaluating Variables 372
Executing, Stepping, and Tracing 373
Breakpoints 379
Exceptions and Events 382
Controlling WinDBG 385
The Magical
Extensions 386
Loading and Controlling Extensions 387
The Important Extension Commands 388
Dealing
with Dump Files 393
Creating Dump Files 393
Opening Dump Files 395
Debugging the Dump 396
Son of
Strike (SOS) 396
Using SOS 397
PART III POWER TOOLS AND TECHNIQUES
FOR .NET
9 Extending the Visual Studio
.NET IDE 407
Extending
with Macros 409
Macro Parameters 410
Problems with Projects 412
Code Elements 413
CommenTater:
The Cure for the Common Potato? 415
Introduction
to Add-Ins 424
Fixing the Add-In Wizard-Generated Code 426
Handling Toolbar Button Issues 429
Creating Tool Windows 430
Creating Options Property Pages with Managed Code 433
The SuperSaver
Add-In 438
The SettingsMaster
Add-In 444
SettingsMaster Implementation Highlights 451
SettingsMaster Future Enhancements 452
10 Managed Exception Monitoring
455
Introduction
to the Profiling API 456
Getting Your Profiler Started 463
ProfilerLib
465
ExceptionMon
467
In-Process Debugging and ExceptionMon 469
Exception
Usage in .NET 475
11 Flow Tracing
479
Hooking
Functions in the Profiling API 479
Requesting Enter and Leave Notifications 480
Implementing the Hook Functions 480
Inlining 482
The Function ID Mapper 483
Using
FlowTrace 484
FlowTrace
Implementation Highlights 485
What's
Next for FlowTrace 487
PART IV POWER TOOLS AND TECHNIQUES
FOR NATIVE CODE
12 Finding Source and Line Information
with Just a Crash Address 491
Creating
and Reading a MAP File 493
MAP File Contents 495
Finding the Source File, Function Name, and Line Number 498
PDB2MAP—Map Files After the Fact 499
Using
CrashFinder 502
Implementation Highlights 505
What's
Next for CrashFinder? 511
13 Crash Handlers
513
Structured
Exception Handling vs. C++ Exception Handling 514
Structured Exception Handling 514
C++ Exception Handling 518
Avoid Using C++ Exception Handling 519
The SetUnhandledExceptionFilter
API Function 525
Using
the CrashHandler API 527
Translating
EXCEPTION_POINTERS Structures 551
Minidumps
553
The MiniDumpWriteDump API 554
Pacifying MiniDumpWriteDump 555
14 Debugging Windows Services
and DLLs That Load into Services 565
Service
Basics 566
The API Dance 566
The Security Dance 568
Debugging
Services 568
Debugging the Core Code 569
Debugging the Basic Service 570
15 Multithreaded Deadlocks
581
Multithreading
Tips and Tricks 581
Don't Do It 582
Don't Overdo It 582
Multithread Only Small, Discrete Pieces 583
Synchronize at the Lowest Level 583
Spin Your Critical Sections 587
Don't Use CreateThread/ExitThread 588
The Default Memory Manager Might Kill You 589
Get the Dump in the Field 590
Review the Code—And Review the Code Again 591
Test on Multiprocessor Machines 592
DeadlockDetection
Requirements 595
High-Level
Design Issues with DeadlockDetection 596
Using
DeadlockDetection 598
Implementing
DeadlockDetection 601
Hooking Imported Functions 601
Implementation Highlights 610
What's
Next for DeadlockDetection? 624
16 Automated Testing
627
The Bane
of Unit Testing: User Interfaces 627
Tester
Requirements 629
Using
Tester 630
Tester Scripts 630
Recording Scripts 635
Implementing
Tester 638
The TESTER.DLL Notification and Playback Implementation 638
Implementing TESTREC.EXE 653
What's
Next for Tester? 665
17 The Debug C Run-Time Library
and Memory Management 667
Features
of the Debug C Run-Time Library 668
Using
the Debug C Run-Time Library 670
The Bug in the DCRT 671
Useful DCRT Functions 675
Choosing
the Right C Run-Time Library for Your Application 677
Using
MemDumperValidator 678
Using MemDumperValidator with C++ 685
Using MemDumperValidator with C 686
Deep Validations 687
Implementing
MemDumperValidator 691
Initialization and Termination in C++ 692
Where Have All the Leak Reports Gone? 693
Using
MemStress 694
Interesting Stress Problems 696
Operating
System Heaps 697
Tricks
for Hunting Down Memory Problems 699
Finding Uninitialized Memory Writes 700
Finding Memory Overruns 701
Killer
Switches 707
The Run-Time Check Switches 707
The Buffer Security Check Switch 714
18 FastTrace: A High-Performance
Tracing Tool for Server Applications 717
The Fundamental
Problem and Its Solution 718
Using
FastTrace 719
Merging Trace Logs 720
FastTrace
Implementation 721
19 Smoothing the Working Set
723
Working
Set Tuning 724
Using
SWS 728
Setting Up the SWS Compiles 729
Running Applications Using SWS 731
Producing and Using the Order File 732
Implementing
SWS 734
The _penter Function 734
The .SWS File Format and Symbol Enumeration 738
The Run Time and Tuning 744
What's
Next for SWS? 747
PART V APPENDIXES
A Reading Dr. Watson Logs
751
Dr. Watson
Logs 753
B Resources for .NET and Windows
Developers 761
Books
762
Software Development 762
Debugging and Testing 763
.NET Technologies 764
C/C++ Language 765
Windows and Windows Technologies 766
The Intel CPU and Hardware 767
Software
Tools 768
Web Sites
769
INDEX 771 |