难度:4;预计完成时间:2小时
gdb是C语言标准的调试器。使用gdb来进行调试是基本操作。(gdb针对二进制文件进行调试,只要是C系列的都可以调试【只要是汇编语言演化来的理论上均可行】)
[info] gdb
编写一个计算1至100的和的C语言程序,编译,运行。 使用gdb进行调试。逐步分析C语言程序的执行过程。回答:当进行计算的时候,运行n和ni有什么区别?这告诉了我们什么?C语言是如何执行循环的?
基于gdb,我们可以对二进制文件进行反汇编。反汇编可以帮助我们检查恶意代码和可能存在的漏洞。反汇编还可以帮助我们了解开发者的想法。
[info] 反汇编
尝试用objdump对上面的代码进行反汇编。
对程序进行调试是对程序进行正确性的测试,有的时候我们还需要对性能进行分析。性能可以从CPUcycle数,执行时间,cache miss的次数,函数递归的层数略知一二。
[info] 程序性能分析
用Python来实现一些排序算法。请使用 cProfile 和 line_profiler 来比较插入排序和快速排序的性能。两种算法的瓶颈分别在哪里?然后使用 memory_profiler 来检查内存消耗,为什么插入排序更好一些?然后再看看原地排序版本的快排。附加题:使用 perf 来查看不同算法的循环次数及缓存命中及丢失情况。
执行python -m cProfile以使用cProfile,为调用的函数加上装饰器@profile以使用line_profiler.
pref的使用方式是:sudo perf stat -e cycles,cache-references,cache-misses python3 sorts.py
[info] 调用路径分析
这里有一些用于计算斐波那契数列 Python 代码,它为计算每个数字都定义了一个函数: 将代码拷贝到文件中使其变为一个可执行的程序。首先安装 pycallgraph和graphviz(如果您能够执行dot, 则说明已经安装了 GraphViz.)。并使用 pycallgraph graphviz -- ./fib.py 来执行代码并查看pycallgraph.png 这个文件。fib0 被调用了多少次?我们可以通过记忆法来对其进行优化。将注释掉的部分放开,然后重新生成图片。这回每个fibN 函数被调用了多少次?
#!/usr/bin/env python
def fib0(): return 0
def fib1(): return 1
s = """def fib{}(): return fib{}() + fib{}()"""
if __name__ == '__main__':
for n in range(2, 10):
exec(s.format(n, n-1, n-2))
# from functools import lru_cache
# for n in range(10):
# exec("fib{} = lru_cache(1)(fib{})".format(n, n))
print(eval("fib9()"))