软件调试实战

软件调试实战
分享
扫描下方二维码分享到微信
打开微信,点击右上角”+“,
使用”扫一扫“即可将网页分享到朋友圈。
作者: [德] ,
2010-02
版次: 1
ISBN: 9787115218858
定价: 45.00
装帧: 平装
开本: 16开
纸张: 胶版纸
页数: 190页
字数: 302千字
正文语种: 简体中文
原版书名: The Developers Guide to Debugging
43人买过
  •   《软件调试实战》主要讲述C/C++程序的调试和分析,书中的调试技术也可以应用于其他语言编写的程序。《软件调试实战》在讲述简单的源代码分析和测试的基础上,讲述了现实的程序中经常遇到的一些问题(如程序链接、内存访问、并行处理和性能分析)并给出了解决方案。
      《软件调试实战》适合软件开发人员、调试人员阅读和使用。   ThorstenGrotker,UlrichHoltmann,HolgerKeding,MarkusWloka4位作者均拥有德国或美国著名高等学府的博士学位,目前都任职于EDA(电子设计自动化)软件领导厂商Synopsys(新思)公司,分别担任研发主管、资深软件工程师等职位,负责开发编译器和调试工具,具有解决各种调试问题的丰富经验。 第1章谁编写软件,谁制造bug(为什么需要本书)1

    第2章系统性调试方法3
    2.1为什么要遵循结构化的过程3
    2.2充分利用机会3
    2.313条黄金规则5
    2.3.1理解需求5
    2.3.2制造失败6
    2.3.3简化测试用例6
    2.3.4读取恰当的错误消息6
    2.3.5检查显而易见的问题6
    2.3.6从解释中分离出事实7
    2.3.7分而治之7
    2.3.8工具要与bug匹配8
    2.3.9一次只做一项更改9
    2.3.10保持审计跟踪9
    2.3.11获得全新观点9
    2.3.12bug不会自己修复9
    2.3.13用回归测试来检查bug修复10
    2.4构建一个好的工具包10
    2.4.1工具箱11
    2.4.2每天运行测试,防止出现bug11
    2.5认清敌人——遇到bug家族13
    2.5.1常见bug13
    2.5.2偶发性bug13
    2.5.3Heisenbug13
    2.5.4隐藏在bug背后的bug14
    2.5.5秘密bug——调试与机密性14
    2.5.6更多读物15

    第3章查找根源——源代码调试器17
    3.1可视化程序行为17
    3.2准备简单的可预测的示例18
    3.3使调试器与程序一起运行18
    3.4学习在程序崩溃时执行栈跟踪21
    3.5学习使用断点21
    3.6学习在程序中导航22
    3.7学习检查数据:变量和表达式22
    3.8一个简单示例的调试会话23

    第4章修复内存问题27
    4.1C/C++中的内存管理——功能强大但很危险27
    4.1.1内存泄漏27
    4.1.2内存管理的错误使用28
    4.1.3缓冲区溢出28
    4.1.4未初始化的内存bug28
    4.2有效的内存调试器28
    4.3示例1:检测内存访问错误29
    4.3.1检测无效的写访问30
    4.3.2检测对未初始化的内存的读取操作30
    4.3.3检测内存泄漏31
    4.4示例2:对内存分配/释放的不完整调用31
    4.5结合使用内存调试器和源代码测试器33
    4.6减少干扰,排查错误33
    4.7何时使用内存调试器34
    4.8约束34
    4.8.1测试用例应该有很好的代码覆盖率34
    4.8.2提供更多计算机资源35
    4.8.3可能不支持多线程35
    4.8.4对非标准内存处理程序的支持35

    第5章剖析内存的使用37
    5.1基本策略——主要步骤37
    5.2示例:分配数组38
    5.3第1步:查找泄漏38
    5.4第2步:设置期望值38
    5.5第3步:测量内存使用39
    5.5.1使用多个输入39
    5.5.2在固定时间间隔停止程序39
    5.5.3用简单工具测量内存使用40
    5.5.4使用top40
    5.5.5使用WindowsTaskManager41
    5.5.6为testmalloc选择相关输入值42
    5.5.7确定机器上的内存是如何被释放的42
    5.5.8使用内存剖析工具43
    5.6第4步:查明大部分内存被哪些数据结构占用了44
    5.7综合练习——genindex示例45
    5.7.1核实没有大的内存泄漏46
    5.7.2估计内存使用46
    5.7.3测量内存使用46
    5.7.4查找使用内存的数据结构47

    第6章解决性能问题51
    6.1分步查找性能bug51
    6.1.1执行前期分析51
    6.1.2使用简单的时间测量方法52
    6.1.3创建测试用例52
    6.1.4使测试用例具有可再现性53
    6.1.5检查程序的正确性53
    6.1.6创建可扩展的测试用例53
    6.1.7排除对测试用例的干扰54
    6.1.8用time命令测量时可能会发生错误和偏差54
    6.1.9选择一个能够揭示运行时间瓶颈的测试用例55
    6.1.10算法与实现之间的差异56
    6.2使用剖析工具58
    6.2.1不要编写自己的剖析工具58
    6.2.2剖析工具的工作原理58
    6.2.3了解gprof59
    6.2.4了解Quantify63
    6.2.5了解Callgrind64
    6.2.6了解VTune66
    6.3分析I/O性能68

    第7章调试并行程序71
    7.1用C/C++编写并行程序71
    7.2调试竞争条件72
    7.2.1使用基本调试器功能来查找竞争条件73
    7.2.2使用日志文件来查找竞争条件74
    7.3调试死锁76
    7.3.1如何确定正在运行的是哪个线程77
    7.3.2分析程序的线程78
    7.4了解线程分析工具78
    7.5异步事件和中断处理程序80

    第8章查找环境和编译器问题83
    8.1环境变更——问题的根源83
    8.1.1环境变量83
    8.1.2本地安装依赖84
    8.1.3当前工作目录依赖84
    8.1.4进程ID依赖84
    8.2如何查看程序正在做什么84
    8.2.1用top来查看进程84
    8.2.2用ps来查找应用程序的多个进程85
    8.2.3使用/proc/来访问进程85
    8.2.4使用strace跟踪对操作系统的调用85
    8.3编译器和调试器也有bug87
    8.3.1编译器bug87
    8.3.2调试器和编译器兼容性问题88

    第9章处理链接问题89
    9.1链接器的工作原理89
    9.2构建并链接对象89
    9.3解析未定义的符号91
    9.3.1丢失链接器参数91
    9.3.2搜索丢失的符号91
    9.3.3链接顺序问题92
    9.3.4C++符号和名称改编93
    9.3.5符号的反改编94
    9.3.6链接C和C++代码94
    9.4具有多个定义的符号95
    9.5信号冲突96
    9.6识别编译器和链接器版本不匹配96
    9.6.1系统库不匹配97
    9.6.2对象文件不匹配97
    9.6.3运行时崩溃98
    9.6.4确定编译器版本98
    9.7解决动态链接问题100
    9.7.1链接或载入DLL100
    9.7.2无法找到DLL文件101
    9.7.3分析载入器问题102
    9.7.4在DLL中设置断点103
    9.7.5提供DLL问题的错误消息104

    第10章高级调试107
    10.1在C++函数、方法和操作符中设置断点107
    10.2在模板化的函数和C++类中设置断点109
    10.3进入C++方法110
    10.3.1用step-into命令进入到隐式函数中112
    10.3.2用step-out命令跳过隐式函数112
    10.3.3利用临时断点跳过隐式函数113
    10.3.4从隐式函数调用返回113
    10.4条件断点和断点命令114
    10.5调试静态构造/析构函数116
    10.5.1由静态初始化程序的顺序依赖性引起的bug117
    10.5.2识别静态初始化程序的栈跟踪118
    10.5.3在静态初始化之前连接调试器118
    10.6使用观察点119
    10.7捕捉信号120
    10.8捕获异常122
    10.9读取栈跟踪124
    10.9.1带调试信息编译的源代码的栈跟踪124
    10.9.2不带调试信息编译的源代码的栈跟踪124
    10.9.3不带任何调试信息的帧125
    10.9.4实际工作中的栈跟踪125
    10.9.5改编后的函数名称126
    10.9.6被破坏的栈跟踪126
    10.9.7核心转储127
    10.10操纵正在运行的程序128
    10.10.1修改变量130
    10.10.2调用函数131
    10.10.3修改函数的返回值132
    10.10.4中止函数调用132
    10.10.5跳过或重复执行个别语句133
    10.10.6输出和修改内存内容133
    10.11在没有调试信息时进行调试135
    10.11.1从栈读取函数参数137
    10.11.2读取局部/全局变量和用户定义的数据类型138
    10.11.3在源代码中查找语句的大概位置139
    10.11.4走查汇编代码140

    第11章编写可调试的代码143
    11.1注释的重要性143
    11.1.1函数签名的注释144
    11.1.2对折中办法的注释144
    11.1.3为不确定的代码加注释144
    11.2采用一致的编码风格144
    11.2.1仔细选择名称145
    11.2.2不要使用“聪明过头”的结构145
    11.2.3不要压缩代码145
    11.2.4为复杂表达式使用临时变量145
    11.3避免使用预处理器宏146
    11.3.1使用常量或枚举来替代宏146
    11.3.2使用函数来替代预处理器宏148
    11.3.3调试预处理器输出149
    11.3.4使用功能更强的预处理器150
    11.4提供更多调试函数151
    11.4.1显示用户定义的数据类型151
    11.4.2自检查代码152
    11.4.3为操作符创建一个函数,以便帮助调试153
    11.5为事后调试做准备153

    第12章静态检查的作用155
    12.1使用编译器作为调试工具155
    12.1.1不要认为警告是无害的156
    12.1.2使用多个编译器来检查代码158
    12.2使用lint158
    12.3使用静态分析工具158
    12.3.1了解静态检查器158
    12.3.2将静态检查器检测到的错误减至(接近)零160
    12.3.3完成代码清理后重新运行所有测试用例160
    12.4静态分析的高级应用161

    第13章结束语163
    附录A调试命令165
    附录B工具资源167
    附录C源代码179
    参考文献189
  • 内容简介:
      《软件调试实战》主要讲述C/C++程序的调试和分析,书中的调试技术也可以应用于其他语言编写的程序。《软件调试实战》在讲述简单的源代码分析和测试的基础上,讲述了现实的程序中经常遇到的一些问题(如程序链接、内存访问、并行处理和性能分析)并给出了解决方案。
      《软件调试实战》适合软件开发人员、调试人员阅读和使用。
  • 作者简介:
      ThorstenGrotker,UlrichHoltmann,HolgerKeding,MarkusWloka4位作者均拥有德国或美国著名高等学府的博士学位,目前都任职于EDA(电子设计自动化)软件领导厂商Synopsys(新思)公司,分别担任研发主管、资深软件工程师等职位,负责开发编译器和调试工具,具有解决各种调试问题的丰富经验。
  • 目录:
    第1章谁编写软件,谁制造bug(为什么需要本书)1

    第2章系统性调试方法3
    2.1为什么要遵循结构化的过程3
    2.2充分利用机会3
    2.313条黄金规则5
    2.3.1理解需求5
    2.3.2制造失败6
    2.3.3简化测试用例6
    2.3.4读取恰当的错误消息6
    2.3.5检查显而易见的问题6
    2.3.6从解释中分离出事实7
    2.3.7分而治之7
    2.3.8工具要与bug匹配8
    2.3.9一次只做一项更改9
    2.3.10保持审计跟踪9
    2.3.11获得全新观点9
    2.3.12bug不会自己修复9
    2.3.13用回归测试来检查bug修复10
    2.4构建一个好的工具包10
    2.4.1工具箱11
    2.4.2每天运行测试,防止出现bug11
    2.5认清敌人——遇到bug家族13
    2.5.1常见bug13
    2.5.2偶发性bug13
    2.5.3Heisenbug13
    2.5.4隐藏在bug背后的bug14
    2.5.5秘密bug——调试与机密性14
    2.5.6更多读物15

    第3章查找根源——源代码调试器17
    3.1可视化程序行为17
    3.2准备简单的可预测的示例18
    3.3使调试器与程序一起运行18
    3.4学习在程序崩溃时执行栈跟踪21
    3.5学习使用断点21
    3.6学习在程序中导航22
    3.7学习检查数据:变量和表达式22
    3.8一个简单示例的调试会话23

    第4章修复内存问题27
    4.1C/C++中的内存管理——功能强大但很危险27
    4.1.1内存泄漏27
    4.1.2内存管理的错误使用28
    4.1.3缓冲区溢出28
    4.1.4未初始化的内存bug28
    4.2有效的内存调试器28
    4.3示例1:检测内存访问错误29
    4.3.1检测无效的写访问30
    4.3.2检测对未初始化的内存的读取操作30
    4.3.3检测内存泄漏31
    4.4示例2:对内存分配/释放的不完整调用31
    4.5结合使用内存调试器和源代码测试器33
    4.6减少干扰,排查错误33
    4.7何时使用内存调试器34
    4.8约束34
    4.8.1测试用例应该有很好的代码覆盖率34
    4.8.2提供更多计算机资源35
    4.8.3可能不支持多线程35
    4.8.4对非标准内存处理程序的支持35

    第5章剖析内存的使用37
    5.1基本策略——主要步骤37
    5.2示例:分配数组38
    5.3第1步:查找泄漏38
    5.4第2步:设置期望值38
    5.5第3步:测量内存使用39
    5.5.1使用多个输入39
    5.5.2在固定时间间隔停止程序39
    5.5.3用简单工具测量内存使用40
    5.5.4使用top40
    5.5.5使用WindowsTaskManager41
    5.5.6为testmalloc选择相关输入值42
    5.5.7确定机器上的内存是如何被释放的42
    5.5.8使用内存剖析工具43
    5.6第4步:查明大部分内存被哪些数据结构占用了44
    5.7综合练习——genindex示例45
    5.7.1核实没有大的内存泄漏46
    5.7.2估计内存使用46
    5.7.3测量内存使用46
    5.7.4查找使用内存的数据结构47

    第6章解决性能问题51
    6.1分步查找性能bug51
    6.1.1执行前期分析51
    6.1.2使用简单的时间测量方法52
    6.1.3创建测试用例52
    6.1.4使测试用例具有可再现性53
    6.1.5检查程序的正确性53
    6.1.6创建可扩展的测试用例53
    6.1.7排除对测试用例的干扰54
    6.1.8用time命令测量时可能会发生错误和偏差54
    6.1.9选择一个能够揭示运行时间瓶颈的测试用例55
    6.1.10算法与实现之间的差异56
    6.2使用剖析工具58
    6.2.1不要编写自己的剖析工具58
    6.2.2剖析工具的工作原理58
    6.2.3了解gprof59
    6.2.4了解Quantify63
    6.2.5了解Callgrind64
    6.2.6了解VTune66
    6.3分析I/O性能68

    第7章调试并行程序71
    7.1用C/C++编写并行程序71
    7.2调试竞争条件72
    7.2.1使用基本调试器功能来查找竞争条件73
    7.2.2使用日志文件来查找竞争条件74
    7.3调试死锁76
    7.3.1如何确定正在运行的是哪个线程77
    7.3.2分析程序的线程78
    7.4了解线程分析工具78
    7.5异步事件和中断处理程序80

    第8章查找环境和编译器问题83
    8.1环境变更——问题的根源83
    8.1.1环境变量83
    8.1.2本地安装依赖84
    8.1.3当前工作目录依赖84
    8.1.4进程ID依赖84
    8.2如何查看程序正在做什么84
    8.2.1用top来查看进程84
    8.2.2用ps来查找应用程序的多个进程85
    8.2.3使用/proc/来访问进程85
    8.2.4使用strace跟踪对操作系统的调用85
    8.3编译器和调试器也有bug87
    8.3.1编译器bug87
    8.3.2调试器和编译器兼容性问题88

    第9章处理链接问题89
    9.1链接器的工作原理89
    9.2构建并链接对象89
    9.3解析未定义的符号91
    9.3.1丢失链接器参数91
    9.3.2搜索丢失的符号91
    9.3.3链接顺序问题92
    9.3.4C++符号和名称改编93
    9.3.5符号的反改编94
    9.3.6链接C和C++代码94
    9.4具有多个定义的符号95
    9.5信号冲突96
    9.6识别编译器和链接器版本不匹配96
    9.6.1系统库不匹配97
    9.6.2对象文件不匹配97
    9.6.3运行时崩溃98
    9.6.4确定编译器版本98
    9.7解决动态链接问题100
    9.7.1链接或载入DLL100
    9.7.2无法找到DLL文件101
    9.7.3分析载入器问题102
    9.7.4在DLL中设置断点103
    9.7.5提供DLL问题的错误消息104

    第10章高级调试107
    10.1在C++函数、方法和操作符中设置断点107
    10.2在模板化的函数和C++类中设置断点109
    10.3进入C++方法110
    10.3.1用step-into命令进入到隐式函数中112
    10.3.2用step-out命令跳过隐式函数112
    10.3.3利用临时断点跳过隐式函数113
    10.3.4从隐式函数调用返回113
    10.4条件断点和断点命令114
    10.5调试静态构造/析构函数116
    10.5.1由静态初始化程序的顺序依赖性引起的bug117
    10.5.2识别静态初始化程序的栈跟踪118
    10.5.3在静态初始化之前连接调试器118
    10.6使用观察点119
    10.7捕捉信号120
    10.8捕获异常122
    10.9读取栈跟踪124
    10.9.1带调试信息编译的源代码的栈跟踪124
    10.9.2不带调试信息编译的源代码的栈跟踪124
    10.9.3不带任何调试信息的帧125
    10.9.4实际工作中的栈跟踪125
    10.9.5改编后的函数名称126
    10.9.6被破坏的栈跟踪126
    10.9.7核心转储127
    10.10操纵正在运行的程序128
    10.10.1修改变量130
    10.10.2调用函数131
    10.10.3修改函数的返回值132
    10.10.4中止函数调用132
    10.10.5跳过或重复执行个别语句133
    10.10.6输出和修改内存内容133
    10.11在没有调试信息时进行调试135
    10.11.1从栈读取函数参数137
    10.11.2读取局部/全局变量和用户定义的数据类型138
    10.11.3在源代码中查找语句的大概位置139
    10.11.4走查汇编代码140

    第11章编写可调试的代码143
    11.1注释的重要性143
    11.1.1函数签名的注释144
    11.1.2对折中办法的注释144
    11.1.3为不确定的代码加注释144
    11.2采用一致的编码风格144
    11.2.1仔细选择名称145
    11.2.2不要使用“聪明过头”的结构145
    11.2.3不要压缩代码145
    11.2.4为复杂表达式使用临时变量145
    11.3避免使用预处理器宏146
    11.3.1使用常量或枚举来替代宏146
    11.3.2使用函数来替代预处理器宏148
    11.3.3调试预处理器输出149
    11.3.4使用功能更强的预处理器150
    11.4提供更多调试函数151
    11.4.1显示用户定义的数据类型151
    11.4.2自检查代码152
    11.4.3为操作符创建一个函数,以便帮助调试153
    11.5为事后调试做准备153

    第12章静态检查的作用155
    12.1使用编译器作为调试工具155
    12.1.1不要认为警告是无害的156
    12.1.2使用多个编译器来检查代码158
    12.2使用lint158
    12.3使用静态分析工具158
    12.3.1了解静态检查器158
    12.3.2将静态检查器检测到的错误减至(接近)零160
    12.3.3完成代码清理后重新运行所有测试用例160
    12.4静态分析的高级应用161

    第13章结束语163
    附录A调试命令165
    附录B工具资源167
    附录C源代码179
    参考文献189
查看详情
系列丛书 / 更多
软件调试实战
机器学习实战
[美]Peter Harrington 著;李锐、李鹏、曲亚东 译
软件调试实战
图灵程序设计丛书:Python基础教程
[挪威]Magnus Lie Hetland 著;司维、曾军崴、谭颖华 译
软件调试实战
JavaScript高级程序设计(第3版)
[美]Nicholas C.Zakas 著;李松峰、曹力 译
软件调试实战
Python编程:从入门到实践
[美]埃里克·马瑟斯(Eric Matthes) 著;袁国忠 译
软件调试实战
R语言实战(第2版)
[美]卡巴科弗(Robert I. Kabacoff) 著;王小宁、刘撷芯、黄俊文 译
软件调试实战
算法(第4版)
[美]Robert、[美]Kevin Wayne 著;谢路云 译
软件调试实战
大数据:互联网大规模数据挖掘与分布式处理
[美]Anand、[美]Jeffrey David Ullman 著;王斌 译
软件调试实战
Spark快速大数据分析
[美]卡劳(Holden Karau)、[美]肯维尼斯科(Andy Konwinski)、[美]温德尔(Patrick Wendell)、[加拿大]扎哈里亚(Matei Zaharia) 著;王道远 译
软件调试实战
图解HTTP
[日]上野·宣 著;于均良 译
软件调试实战
MySQL必知必会
[英]福塔(Ben Forta) 著;刘晓霞、钟鸣 译
软件调试实战
Objective-C基础教程 第2版
[美]Scott、[美]Waqar、[美]Mark Dalrymple 著;周庆成 译
软件调试实战
算法图解
袁国忠 译
相关图书 / 更多
软件调试实战
软件工程:经典、现代和前沿
孙艳春 主编, 黄罡,邓水光 编著
软件调试实战
软件利润流 英文限量版
(美)杰森·坦纳(Jason Tanner)
软件调试实战
软件逆向分析技术及应用
鲁宏伟 陈凯 邓贤君 许雷永
软件调试实战
软件性能测试实战教程(LoadRunner与JMeter)
周百顺 主编;张伟
软件调试实战
软件工程专业英语(第2版)
宋晓涛 谢红薇 郭晓红
软件调试实战
软件工程--理论与实践
毛新军 董威
软件调试实战
软件需求分析(微课版)
李美蓉 何中海
软件调试实战
软件自动化测试入门攻略
杨定佳
软件调试实战
软件工程(第4版 英文版)
(美) 莎丽·劳伦斯·弗里格(Shari Lawrence Pfleeger)
软件调试实战
软件性能测试、分析与调优实践之路(第2版)
张永清
软件调试实战
软件灵活性设计:如何避免陷入编程困境 [美]克里斯·汉森
(美)克里斯·汉森 (美)杰拉尔德·杰伊·萨斯曼
软件调试实战
软件开发珠玑:穿越50年软件往事的60条戒律
(美)Karl Wiegers(卡尔·魏格斯)
您可能感兴趣 / 更多
软件调试实战
悉达多 外国现当代文学 [德]赫尔曼·黑塞 新华正版
[德]赫尔曼·黑塞
软件调试实战
从我不配到我值得:帮孩子建立稳定的价值感 [德]乌里珂·杜普夫纳
[德]乌里珂·杜普夫纳(Ulrike Dopfner)
软件调试实战
伽达默尔著作集(第6卷)
[德]汉斯-格奥尔格·伽达默尔 著
软件调试实战
奥夫特丁根(德国浪漫主义诗人诺瓦利斯未完成长篇小说,以“蓝花”作为浪漫主义的象征,诺瓦利斯因此被誉为“蓝花诗人”)
[德]诺瓦利斯
软件调试实战
妈妈怎么了?
[德]科尔斯滕·波伊
软件调试实战
歌德谈话录
[德]约翰·沃尔夫冈·冯·歌德 著 [德]约翰·彼得·爱克曼 辑,安书祉 译 范大灿 注
软件调试实战
法律研习的方法:作业、考试和论文写作(第10版)法律人进阶译丛 德国法学研究专业学习方法
[德]托马斯·M. J.默勒斯 著, 申柳华 等 译
软件调试实战
康德:实践理性批判-崇文学术译丛·西方哲学03
[德]康德 著,关文运 译
软件调试实战
诺奖作家给孩子的阅读课·人生智慧(3-9年级,莫言余华的文学启蒙,垫高阅读起点,提升作文能力)
[德]黑塞等
软件调试实战
骨盆脆骨折
[德]波尔·玛丽亚·罗门斯
软件调试实战
世界上究竟有没有胡萝卜味的苍蝇?(蹦蹦和跳跳桥梁书系列)
[德]玛笛亚斯·约特克/著
软件调试实战
(精美绘本)劳拉的星星睡前故事(全21册)
[德]【德】克劳斯·鲍姆加特(【德】克劳斯·鲍姆加特)