第Ⅰ部分 调试概论 3
第1章 错误:问题出在那里,如何解决 3
1.1 错误及其调试 3
1.1.1 什么是错误 3
1.1.2 进程错误及其解决方案 5
1.1.3 制定调试计划 9
1.2 调试的先决条件 10
1.2.1 技能组合 10
1.2.2 学习技能组合 12
1.3 调试过程 13
1.3.1 第1步:复制错误 14
1.3.4 第4步:分解并解决错误 15
1.3.3 第3步:始终假定错误是你自己的问题 15
1.3.2 第2步:描述错误 15
1.3.5 第5步:进行有创见的思考 16
1.3.6 第6步:杠杆工具 16
1.3.7 第7步:开始繁重的调试工作 17
1.3.8 第8步:校验错误已被更正 17
1.3.9 第9步:学习与交流 18
1.3.10 调试过程的决定性秘诀 19
1.4 小结 19
第2章 开始调试 20
2.1 跟踪变更直到项目结束 20
2.1.1 版本控制系统 21
2.1.2 错误跟踪系统 23
2.1.3 选择正确的系统 24
2.2.1 用调试符来连编所有的构件 25
2.2 制定构建调试系统的进度表 25
2.2.2 警告与错误同等重要 26
2.2.3 了解在何处装截DLL 28
2.2.4 设计发布构件的轻便诊断系统 34
2.3 日常连编和冒烟测试是必须遵循的 35
2.3.1 日常构件 36
2.3.2 冒烟测试 37
2.4 立即连编安装程序 38
2.5 QA必须对调试构件进行测试 38
2.6 小结 39
第3章 边编码边调试 40
3.1 注意声明 41
3.1.1 如何声明,声明什么 42
3.1.2 不同类型的Visual C++和Visual Basic声明 51
3.1.3 SUPERASSERT 59
3.2 跟踪、跟踪、跟踪、再跟踪 67
3.3 注意注释 68
3.4 相信自己,但要校验(单元测试) 69
3.5 小结 71
第Ⅱ部分 高效率的调试 75
第4章 调试器的工作原理 75
4.1 Windows调试器的类型 75
4.1.1 用户模式调试器 76
4.1.2 内核模式调试器 76
4.2 Windows 2000操作系统为调试对象提供的支持 81
4.2.1 Windows 2000堆阵检查 81
4.2.2 在调试器中自动启动 83
4.2.3 快速中断项 84
4.3 MinDBG:一个简单的Win32调试器 85
4.4 WDBG:真正的调试器 96
4.4.1 内存读写操作 98
4.4.2 断点和单步执行 100
4.4.3 符号表、符号引擎和堆栈遍历 109
4.4.4 Step Into、Step Over和Step Out功能 126
4.4.5 WDBG调试器的一个有趣的开发问题 127
4.5 如果需要编写自己的调试器 130
4.6 WDBG调试器之后是什么? 131
4.7 小结 131
第5章 使用Visual C++调试器进行强有力的调试 133
5.1 高级断点及其用法 133
5.1.1 高级断点语法和位置断点 134
5.1.3 在系统或输出的函数中设置断点 136
5.1.2 在任何函数上快速中断 136
5.1.4 位置断点修饰符 138
5.1.5 全局表达式和条件断点 141
5.1.6 Windows消息断点 144
5.2 远程调试 145
5.3 技巧及窍门 148
5.3.1 设置断点 148
5.3.2 Watch窗口 149
5.4 小结 156
第6章 使用x86汇编语言和Visual C++调试器Disassembly窗口进行强有力的调试 158
6.1 CPU的基础知识 159
6.1.1 寄存器 159
6.1.2 指令格式和内存编址 162
6.2 关于Visual C++内联汇编器 163
6.3.1 堆栈处理 164
6.3 需要了解的指令 164
6.3.3 常见的序列:函数入口和出口 166
6.3.2 最常用的几个简单指令 166
6.3.4 变量访问:全局变量、参数和局部变量 168
6.3.5 调用进程和返回指令 172
6.4 调用约定 173
6.5 需要了解的其他指令 179
6.5.1 数据处理 180
6.5.2 指针处理 182
6.5.3 比较和测试 183
6.5.4 条约和分支指令 183
6.5.5 循环 186
6.5.6 字符串处理 187
6.6.1 FS寄存器访问 191
6.6 常见的汇编语言结构 191
6.6.2 结构和类引用 192
6.7 完整的例子 194
6.8 Disassembly窗口 197
6.8.1 导航功能 197
6.8.2 在堆栈上查看参数 198
6.8.3 Set Next Statement命令 200
6.8.4 Memory窗口和Disassembly窗口 201
6.9 技巧和诀窍 204
6.9.1 Endians 205
6.9.2 垃圾代码 205
6.9.3 寄存器和Watch窗口 205
6.10 小结 206
6.9.4 从ASM文件中学习 206
第7章 使用Visual Basic调试器进行强有力的调试 207
7.1 Visual Basic P代码 207
7.1.1 关于P代码的历史教训 208
7.1.2 使用P代码衍生出来的问题 209
7.2 错误陷阱:Break In或Break On选项 211
7.2.1 Break On All Errors功能 211
7.2.2 Break On Unhandled Errors功能项 212
7.2.3 Break In Class Modules功能项 212
7.2.4 对非常好的错误陷阱的最后一条要求 212
7.3 Visual Basic调试窗口 213
7.3.1 Locals窗口 213
7.3.2 Immediate窗口 214
7.3.3 Watch窗口 215
7.4 技巧和窍门 216
7.4.1 将Run To Cursor按钮添加到Debug工具栏上 216
7.4.2 不要使用Compile On Demand功能 216
7.4.3 Group Project(组合项目)是进行调试的好方法 217
7.4.4 Visual Basic调试可能会与现实冲突 217
7.5 小结 217
第Ⅲ部分 功能强大的工具和技术 221
第8章 仅通过崩溃地址就可以找出源代码信息和行信息 221
8.1 创建和阅读MAP文件 221
8.1.1 MAP文件的内容 223
8.1.2 查找函数、源文件和代码行号 226
8.2 使用CrashFinder实用程序 227
8.2.1 实施要点 229
8.3 CrashFinder之后是什么 236
8.4 小结 237
第9章 崩溃处理程序 238
9.1 结构化异常处理与C++异常处理的比较 238
9.1.1 结构化异常处理(SEH) 239
9.1.2 C++异常处理 242
9.1.3 结合使用SEH和C++异常处理 243
9.2 SetUnhandledExceptionFilter API函数 247
9.3 使用CrashHandler API函数 248
9.4 转化EXCEPTION_POINTERS结构 283
9.5 小结 285
第10章 调试Windows 2000服务和加载到服务中的DLL 286
10.1 服务的基本知识 286
10.1.1 API问题 287
10.1.2 安全性问题 288
10.2 调试服务 289
10.2.1 调试核心代码 289
10.2.2 调试基本服务 290
10.2.3 进行实际的调试 294
10.3 小结 294
第11章 多机器多进程跟踪 295
11.1 TraceSrv要求 295
11.2 TraceSrv和DCOMCNFG 306
11.3 使用TraceSrv的初始化问题 308
11.4 TraceView和安全性 310
11.5 使用TraceSrv 312
11.6 小结 314
12.1.1 不要做它 316
12.1 多线程提示和技巧 316
第12章 多线程死锁 316
12.1.2 只在很小的离散部分使用多线程 317
12.1.3 在最低级别上同步 317
12.1.4 检查代码-并再次检查代码 317
12.1.5 在多处理器机器上进行测试 318
12.2 DeadlockDetection的要求 318
12.3 DeadlockDection的高级设计问题 320
12.4 使用DeadlockDetection 323
12.5 实现DeadlockDetection 325
12.5.1 挂接导入的函数 325
12.5.2 实现关键 335
12.6 DeadlockDetection的下一步目标是什么? 349
12.7 小结 350
第13章 自动化测试 351
13.1 单元测试的祸根:用户界面 351
13.2 Tester要求 352
13.3 使用Tester 353
13.4 实现Tester 358
13.5 Tester的下一步目标是什么? 378
13.6 小结 379
第14章 限制OutputDebugString调用 380
14.1 Also-Ran解决方案 380
14.2 LIMODS要求 381
14.3 使用LIMODS 382
14.3.1 与MFC共存 382
14.3.2 从代码中调用LIMODS 383
14.3.3 选择从哪个源文件中跟踪 386
14.4 实现LIMODS 387
14.4.1 确定源代码范围 387
14.4.2 解释ROLOM文件 388
14.4.3 从LOM文件中排除源文件 389
14.4.4 LIMDOSDLL.DLL挂接什么 390
14.4.5 处理_cdecl挂钩 390
14.4.6 按序数值导出的挂接函数 392
14.4.7 一般实现问题 396
14.5 LIMODS的下一步目标 397
14.6 小结 398
第15章 调试C运行时间库 399
15.1 调试C运行时间(DCRT)库的功能 399
15.2 使用调试C运行时间(DCRT)库 400
15.3 为应用程序选择正确的C运行时间库 403
15.4 使用MemDumperValidator扩展程序 404
15.4.1 在C++环境下使用MemDumperValidator扩展程序 413
15.4.2 使用以C编写的MemDumperValidator 414
15.4.3 深度确认 415
15.5 MemDumperValidstor函数的实现 419
15.5.1 C++中的初始化和终止 421
15.5.2 所有的内存泄露报告都到何处去了 422
15.6 使用MemStress扩展程序 424
15.6.1 一个令人感兴趣的重要问题 425
15.7 小结 426
第Ⅳ部分 附录 429
附录A 阅读Dr.Watson记录文件 429
附录B 给Windows开发者的资源 440