编程调试解bug和性能分析 Debugging and Profiling Testing TDD Logging gdb Sanitizers Coredump Dynamic Tracin

编程调试解bug和性能分析 Debugging and Profiling

在编程中,调试(Debugging)、性能分析(Profiling)、测试(Testing)、测试驱动开发(TDD)、日志(Logging)、GDB调试器、Sanitizers、Core Dump以及动态追踪(Dynamic Tracing)等工具和技术都是帮助开发者找出并修复代码中的错误(bug)、优化程序性能的重要方法。下面我将分别简要介绍这些概念和技术。

  • 调试(Debugging)和性能分析(Profiling)
  • 调试:是发现和修复代码中的错误(bug)的过程。这通常涉及到使用调试器(如GDB)来单步执行代码、查看变量值、设置断点等。调试还包括阅读和分析错误消息、查看日志以及使用其他调试工具。
  • 性能分析:是评估程序在运行时性能的过程。性能分析可以帮助开发者找出程序的性能瓶颈,如CPU、内存或磁盘I/O的使用情况。常用的性能分析工具包括gprof、Valgrind的Helgrind和Massif工具、以及Linux下的perf工具等。
  • 测试(Testing)
    测试是确保程序按预期工作的关键步骤。它包括单元测试(Unit Testing)、集成测试(Integration Testing)、系统测试(System Testing)等。单元测试是测试代码中的最小可测试单元(如函数或类)的过程。集成测试则是测试不同代码单元之间的交互。系统测试则是测试整个系统是否满足需求。
  • 测试驱动开发(TDD)
    TDD是一种软件开发方法,其中测试在开发之前编写,并且测试指导开发过程。在TDD中,开发者首先编写一个失败的测试用例,然后编写足够的代码以使测试通过。这种方法有助于确保代码满足需求,并且鼓励开发者编写简洁、可测试的代码。
  • 日志(Logging)
    日志是记录程序运行时信息的一种方式。通过查看日志,开发者可以了解程序的执行过程、查找潜在问题、跟踪错误等。日志通常包括程序的输出、变量的值、时间戳等信息。
  • GDB调试器
    GDB是GNU调试器(GNU Debugger)的缩写,是一个强大的Unix下的程序调试工具。GDB允许开发者在程序运行时设置断点、单步执行代码、查看变量值等。它对于调试复杂程序非常有用。
  • Sanitizers
    Sanitizers(如AddressSanitizer、ThreadSanitizer等)是编译器和运行时工具,用于检测内存错误(如缓冲区溢出、内存泄漏等)和线程错误(如数据竞争)。这些工具可以帮助开发者在早期阶段发现并修复潜在的错误。
  • Core Dump
    当程序崩溃时,操作系统可能会生成一个core dump文件,该文件是程序崩溃时内存内容的快照。通过分析core dump文件,开发者可以了解程序崩溃时的状态,如CPU寄存器值、堆栈指针、函数调用栈等,从而找出崩溃的原因。
  • 动态追踪(Dynamic Tracing)
    动态追踪是一种在程序运行时监视其执行的技术。通过动态追踪,开发者可以实时地查看程序的执行路径、函数调用、内存访问等信息。这对于调试复杂程序、优化性能以及理解程序行为非常有用。
  • Profiling
    在前面已经提到,Profiling是评估程序在运行时性能的过程。它可以帮助开发者找出程序的性能瓶颈,并提供优化建议。Profiling工具可以分析程序的CPU使用率、内存使用情况、磁盘I/O等。

这些技术和工具在软件开发中起着至关重要的作用,它们帮助开发者更好地理解和控制他们的代码,确保程序的质量和性能。

Testing

  • Test-driven development(TDD) 软件开发流程
    • Fake and mock object methods
  • 也可参考【C++笔记】《The Art of Writing Readable Code》- chpt 14
  • 也可参考【protobuf等基本工具笔记】gtest

MIT 6.NULL - Debugging and Profiling

Debugging

Printf Debugging and Logging

脑力劳动debug,借助打印信息思考和推断问题所在

信息除了Printf,还可以Logging,更灵活(可以输出到文件、sockets、remote servers),可复用

Here is an example code that logs messages:

$ python logger.py
# Raw output as with just prints
python logger.py log
# Log formatted output
$ python logger.py log ERROR
# Print only ERROR levels and above
$ python logger.py color
# Color formatted output

利用颜色信息: ANSI escape codes

#!/usr/bin/env bash
for R in $(seq 0 20 255); do
    for G in $(seq 0 20 255); do
        for B in $(seq 0 20 255); do
            printf "\e[38;2;${R};${G};${B}m█\e[0m";
        done
    done
done
Third party logs
  • 一个简化版 Google’s logging

    • https://github.com/google/re2/blob/main/util/logging.h
  • UNIX系统中第三方库的log常存在/var/log

    • the NGINX webserver places its logs under /var/log/nginx
  • systemd, a system daemon that controls many things in your system such as which services are enabled and running

    • /var/log/journal,可用journalctl显示
    • macOS上var/log/system.log,但更多人用system log,用 log show 显示
    • 参考data wrangling,需要对log信息处理,也可以用lvav,体验更好
logger "Hello Logs"
# On macOS
log show --last 1m | grep Hello
# On Linux
journalctl --since "1m ago" | grep Hello
Debuggers
gdb

C++: gdb (and its quality of life modification pwndbg) and lldb

Debugging with GDB 教程

gdb:c(continue), l(ist), s(tep), n(ext), b(reak), p(rint), r(eturn), run, q(uit), watch

  • up, down

    • up n
    • up-silently n
  • 特有:start, finish, cond, disable, where

    • cond 3 this==0xXXX
  • 参数

    • gdb --args sleep 20 debug带参数的binary
    • -q quiet模式
    • -ex: 执行gdb命令
      • -ex "run"
  • bt(backtrace), frame X 进帧

  • info b

  • watch -l 同时监视表达式本身和表达式指向的内容

  • attach $pid debug正在运行的进程

  • ptype 打印变量类型;打印stl使用 python pretty print

  • gcore attach后制造core文件

  • call

    • call (void)'xxx::Logger::setLogLevel'(3) 注意引号让gdb不会因为找不到符号而报错
    • how does gdb call functions
//增加print的可读性
set print pretty on/off
//显示完整 STL 结构
set print elements 0

//显示智能指针对象指向的变量
p ((Object*) my_ptr)->attribute //利用类型转换
p *(my_ptr._M_ptr)
  
//显示vector内部值
p *(my_vec._M_impl._M_start)@my_vec.size()  //打印大小
p *(my_vec._M_impl._M_start+0)
p (my_vec._M_impl._M_start)[N-1] //打印第N个成

你可能感兴趣的:(bug,tdd,gdb)