【文字版】Windows用户态程序高效排错
第1章比工具、技巧和经验都重要的是你的思考——从四个风格迥异的案例说起 1.1绝望的性能问题:ADO NET2.0竟然比1.0要慢 1.1.1问题描述 1.1.2悲观和绝望 1.1.3换位思考 1.1.4排错 1.1.5结论和收获 1.1.6题外话和相关讨论 Safehandle的更多讨论 平衡、取舍、双赢和RFC1925 Profiler的下载地址和相关资源 1.2不可思议:一个API同时打开了两个文件 1.2.1问题描述 1.2.2第一印象 1.2.3深入分析 1.2.4革命尚未成功 1.2.5结论 1.2.6题外话和相关讨论 MSDN是最值得信赖的吗 你敢说CPU坏了 DWORD和文件长度 程序输出0xcdcdcdcd,想到了什么 1.3简单的问题最棘手:稀疏平常的ASP NETSessionLost问题 1.3.1问题描述 1.3.2制定策略 1.3.3具体操作和结论 1.3.4题外话和相关讨论 排查sessionlost的经验 1.4本可以做得更好:SharePoint中文界面变英文 1.4.1问题描述 1.4.2排错步骤 1.4.3错过的线索 第2章汇编、异常、内存、同步和调试器——重要的知识点和神兵利器 2.1排错的工具:调试器Windb g 2.1.1调试器的功能:检查代码和资料,保存dump文件,断点控制程序的执行 2.1.2符号文件(Symbolfile),把二进制和源代码对应起来 2.1.3一个简单的上手程序 2.1.4用InternetExplorer来操练调试器的基本命令 vertarget检查进程概况 !peb显示ProcessEnvironmentBlock lmvm检查模块的加载信息 .reload/!sym加载符号文件 lmf列出当前进程中加载的所有模块 r,d,e寄存器,内存的检查和修改 !address显示内存页信息 S搜索内存 !runaway检查线程的CPU消耗 ~切换目标线程 k,kb,kp,kv,kn检查callstack u反汇编 x查找符号的二进制地址 dds对应二进制地址的符号 2.1.5检查程序资料的小例子 .frame在栈中切换以便检查局部变量 dt格式化显示资料 2.1.6用Windbg控制程序进行实时调试(LiveDebug) WtWatchandTrace,跟踪执行的强大命令 断点和条件断点(conditionbreakpoint),高效地控制观测目标 伪寄存器,帮助保存调试的中间信息 StepOut的实现 2.1.7远程调试(Remotedebug) 2.1.8如何通过Windbg命令行让中文魔兽争霸运行在英文系统上 2.1.9Dump文件 2.1.10CDB、NTSD和重定向到KernelDebugging 2.1.11DebuggerExtension,扩展Windbg的功能 2.2读懂机器的语言:汇编,CPU执行指令的最小单元 2.2.1需要用汇编来排错的常见情况 案例分析:用汇编读懂VC编译器的优化 问题描述 我的分析 案例分析:VC2003编译器的bug、debug模式正常,release模式会崩溃 例子程序 跟踪汇编指令来分析 案例分析:臭名昭著的DLLHell如何导致ASP NET出现ServerUnavailable 2.2.2题外话和相关讨论 Release比Debug快吗 2.3理解操作系统对程序的反馈:异常(Exception)和通知(DebugEvent) 2.3.1异常(Exception)的方方面面和一篇字字珠玑的文章 案例分析:如何让C++像C#一样打印出函数调用栈(callstack) 2.3.2Adplus,抓取dump的方便工具 案例分析:华生医生(Dr.Watson)在什么情况下不能记录Dump文件 问题描述 背景知识 问题分析 新的做法 问题解决了,可是为什么华生医生(Dr.Watson)抓不到dump呢 2.3.3通知(DebugEvent)是操作系统跟调试器交流的一种方法 案例分析:VB6的版本问题 2.3.4题外话和相关讨论 错过第一现场后还从dump中分析出线索吗 Adplus,天天都用的工具 未处理异常发生后的主动退出 如何调试UnhandledExceptionFilter 2.4平坦内存空间中的层次结构:Heap和Stack 2.4.1Heap是对平坦空间的高效管理和利用 2.4.2PageHeap,调试Heap问题的工具 简单例子的多种情况 Heap上的内存泄漏和内存碎片 2.4.3Stackoverrun/corruption 2.4.4题外话和相关讨论 PageHeap的/unaligned参数 Heaptrace,系统帮你记录下每次Heap的操作 为何才分配了300MB内存,就报告Outofmemory 2.5找准排查问题的对应层次 2.5.1从C运行库看层次 2.5.2简单的_CRTDBG_MAP_ALLOC定义就可以让内存泄漏无可遁形 2.5.3BSTRCache,建立在Heap之上的COM字符串内存管理 2.5.4题外话和相关讨论 CRTDebugHeap一定对Debug有帮助吗 C++中new操作符的尴尬 2.6理清多个线程对资源的竞争:同步和锁 2.6.1句柄泄漏、死锁和线程争用,三个典型问题 句柄泄漏(HandleLeak) 死锁(Deadlock) 线程争用(contention) 2.6.2Windbg中的对应排错 !handle检查句柄信息 !htrace检查操作句柄的历史记录 !cs列出CriticalSection的详细信息 排查CriticalSectionleak(OrphanCriticalSection) Invalidhandleexception 案例分析:ArrayList.Add的时候发生IndexOutOfRangeException 问题描述 这个异常不简单 具体操作 结论 2.7调试和设计 2.7.1一位热心朋友的提问 案例分析:反被聪明误 第3章.NETFramework的原理和SOS调试——剖析CLR程序和CLR本身 3.1MetaData、JIT、GC和Exception的关键点 3.1.1MetaData(元资料)和引擎初始化 3.1.2JIT动态编译 3.1.3GC内存管理 3.1.4ExceptionHandling异常处理 3.2用Windbg探索CLR的实现 3.2.1开源的CLR实现:Rotor 3.2.2对一个Helloworld的WinForm程序庖丁解牛 mscoree!_CorExeMainCLR引擎的入口 EEStartupHelper重要的引擎初始化函数 mscorwks!SystemDomain::ExecuteMainMethod执行托管代码的入口 CallDescr/MakeJitWorkerJit引擎发动的地方 NtUserWaitMessage托管程序完成加载 gc_heap::allocate_more_space/GCHeap::GarbageCollect通过GC管理内存的分配和 释放 AppDomain,ThreadPool,Exception,StackWalk,Security都是有趣的话题 3.3通过SOS快捷方便地调试托管程序 3.3.1CLR让托管程序的调试变得非常简单 3.3.2SOS的命令介绍 3.4用简单的程序演示SOS的常见操作 3.4.1.loadSOS加载SOS到Windbg 3.4.2!dumpheap统计托管内存使用信息 3.4.3!do显示托管对象的详细信息 3.4.4!gcroot查找托管对象的引用关系 案例分析:ASP NETHighCPU和更多的CLR命令演示 !threads查看托管线程 !tp查看线程池和CPU占用率 !SyncBlk查看托管线程的lock !ip2md映像内存地址到托管函数名 !savemodule保存模块到本地以便用reflector分析 著名的blog:Ifbrokenitis,fixityoushould 3.5题外话和相关讨论 3.5.1ReleaseCOMObject释放COM对象时候的两难困境 3.5.2PInvoke应该Pin住内存防止崩溃 3.5.3Pin住内存又会导致内存碎片 3.5.4臭名昭著的mixedDLLloadingdeadlock 3.5.5有趣且有用的练习和更多的资料 第4章崩溃,性能和资源泄漏——分享一些经验 4.1排错开始前的准备工作 4.1.1用正确的态度对待问题 4.1.2用简单的提问缩小排错的范围 4.1.3通过MPSREPORT获取系统的详细信息 4.1.4通过简单的Dump分析获取基本信息 4.2崩溃(Crash) 4.2.1崩溃的万千种不同死相 4.2.2准确获取Dump Adplus:最容易上手的dump脚本 华生医生(drWatson) 通过ImageFileExecutionOptions让调试器随目标程序一起启动 COM+和ASP NET的dump获取需要特殊配置 4.2.3crashdump中需要重点关注的信息 案例分析:VC程序的崩溃 问题描述 MessageBox嵌套调用 从源代码中发现的疑点 从This指针找崩溃的根源 结论 4.2.4小结和更多的资源 4.2.5题外话和相关讨论 HeapCorruption StackCorruption 4.3性能(Performance) 4.3.1“你真牛,不如你再给我缩短10秒吧!”不是想要多快就能调到多快 4.3.2性能调优的步骤,CPU利用率是关键 4.3.3无所不知的性能监视器 使用性能监视器的基本步骤 重要的计数器 案例分析:博客园的性能问题 案例分析:堵塞在SqlCommand.ExecuteReader上就一定在等sql吗 问题背景 案例分析:堵塞在Assembly.Load上的deadlock 问题背景 案例分析:196个线程织成的一张网 问题背景 小结 4.3.4用Profiler精确定位性能瓶颈 案例分析:DataTable中foreach和forloop性能差了50% 问题背景 4.3.5题外话和相关讨论 Taskmanager跟performancemonitor的差别 性能监视器的超级用法 C++跟C#到底谁快 没有profiler怎么办 4.4资源泄漏(ResourceLeak) 4.4.1资源泄漏分轻重缓急 4.4.2内存泄漏排错的基本步骤 泄漏了什么,谁分配的,为什么无法释放 定位泄漏内存的类型和增长趋势 区分managedheapleak和nativeleak 案例分析:IE7的内存泄漏 问题描述 重现问题和基本分析 用传统的Pageheap+UMDH找到问题根源 方便强大的IISDiagnostics工具 结论 分析IISDiag 4.4.3托管内存泄漏 案例分析:objectchain让排错简单明了 问题背景 案例分析:一个bt的案例 碎片的其他原因 4.4.4句柄泄漏(HandleLeak) 4.4.5题外话和相关讨论 GDILeak Desktopheapissue
暂无评论