3.1.3使用未初始化的值46
3.2调试内存损坏47
3.2.1初始调查49
3.2.2内存调试工具53
3.2.3堆与栈内存损坏对比53
3.2.4工具箱54
3.3实战故事2:神秘的字节序转换55
3.3.1症状55
3.3.2分析和调试56
3.3.3错误和有价值的点64
3.4实战故事3:覆写栈变量65
3.4.1症状65
3.4.2分析和调试65
3.5本章小结68
第4章C++对象布局69
4.1对齐和大小端69
4.1.1对齐69
4.1.2大小端70
4.2C++对象布局71
4.3实战故事4:访问已经释放的数据94
4.3.1症状94
4.3.2分析和调试94
4.4搜索引用树95
4.5本章小结101
第5章优化后的二进制102
5.1调试版和发行版的区别102
5.2调试优化代码的挑战106
5.3汇编代码介绍108
5.3.1寄存器109
5.3.2指令集111
5.3.3程序汇编的结构113
5.3.4函数调用习惯116
5.4分析优化后的代码127
5.5调试优化后的代码示例130
5.6本章小结141
第6章进程镜像142
6.1二进制文件格式144
6.2运行期加载和链接148
6.3进程映射表153
6.3.1可执行文件154
6.3.2共享库156
6.3.3线程栈157
6.3.4无名区域157
6.3.5拦截158
6.3.6链接时替换158
6.3.7预先加载代理函数159
6.3.8修改导入和导出表159
6.3.9对目标函数进行手术改变164
6.3.10核心转储文件格式166
6.3.11核心转储文件分析工具169
6.4本章小结170
第7章调试多线程程序171
7.1竞争条件171
7.2它是竞争条件吗172
7.3调试竞争条件174
7.4实战故事5:记录重要区域175
7.4.1症状175
7.4.2分析调试175
7.5死锁177
7.6本章小结179
第8章更多调试方法180
8.1重现错误180
8.1.1归因181
8.1.2收集环境信息182
8.1.3重建环境184
8.2防止未来的bug184
8.2.1知识保留和传递185
8.2.2增强提前检查185
8.2.3编写更好调试的代码185
8.3不要忘记这些调试规则189
8.3.1分治法189
8.3.2退一步,获取新的观点189
8.3.3保留调试历史190
8.4逆向调试190
8.4.1rr:RecordandReplay191
8.4.2rr注意事项191
8.5本章小结192
第9章拓展调试器能力193
9.1使用Python拓展GDB193
9.1.1美化输出194
9.1.2编写自己的美观打印器195
9.1.3将重复的工作变成一个命令197
9.1.4更快地调试bug198
9.1.5使用Python设置断点200
9.1.6通过命令行来启动程序和设置断点203
9.2GDB自定义命令203
9.3本章小结206
第10章内存调试工具207
10.1ptmalloc’sMALLOC_CHECK_208
10.2GoogleAddressSanitizer212
10.3AccuTrak213
10.4有效地调试内存损坏225
10.5实战故事6:内存管理器的崩溃问题228
10.5.1症状229
10.5.2分析和调试229
10.6本章小结235
第11章CoreAnalyzer236
11.1使用示例237
11.2主要功能239
11.2.1搜索引用的对象(水平搜索)239
11.2.2查询地址及其底层对象(垂直搜索)240
11.2.3内存模式分析241
11.2.4查询堆内存块242
11.2.5堆遍历(检查整个堆以发现损坏并获取内存使用统计)242
11.3本章小结246
第12章更多调试工具247
12.1strace247
12.1.1常用功能247
12.1.2常用附加选项248
12.2实战故事7:僵尸进程248
12.2.1遇到难题248
12.2.2揭示bug的真相249
12.3Perf249
12.4eBPF250
12.4.1准备环境251
12.4.2编写代码251
12.4.3编译程序252
12.4.4加载和运行程序254
12.5实战故事8:链接问题255
12.5.1切入255
12.5.2更奇怪的事情258
12.5.3柳暗花明259
12.5.4补充260
12.5.5结论261
12.6实战故事9:临时变量的生命周期261
12.7本章小结264
第13章崩溃发送机制265
13.1客户端266
13.2远程报告收集服务器267
13.3终端集成器268
13.4本章小结268
第14章内存泄漏269
14.1为什么RAII是基石269
14.2分析270
14.3调试内存泄漏273
14.4本章小结275
第15章协程276
15.1C++协程277
15.2协程的切分点279
15.3协程之诺281
15.4本章小结283
第16章远程调试284
16.1GDB远程调试285
16.2VisualStudio远程调试286
16.3本章小结287
第17章容器世界288
17.1容器示例288
17.2容器应用289
17.3C/C++容器调试291
17.4实战故事10:CrashLoopBackOff292
17.5实战故事11:livenessfailure292
17.6本章小结294
第18章尽量不要调试程序295
18.1借助编译器来提前发现错误295
18.2编写简短的实验代码295
18.3日志和监控296
18.3.1日志296
18.3.2监控297
18.4遵循最佳编码实践297
18.5本章小结298
附录A调试混合语言299
附录B在Windows/x86环境下进行程序调试301
B.1PE文件格式301
B.2WindowsMinidump格式306
附录C一个简单的C++coroutine程序309