Skip to content

Latest commit

 

History

History
261 lines (182 loc) · 6.52 KB

303-529665-函数的调试与反编译.sy.md

File metadata and controls

261 lines (182 loc) · 6.52 KB
show version enable_checker
step
1.0
true

函数

回忆

  • 上次我们定义了函数
    • 函数就是一个套路、流程、惯用方法
    • 我们可以把他定义出来
    • 然后再调用
  • 调用函数
    • 定义函数就是把相关的代码封装到一个函数里面
    • 以后只要调用函数
    • 相关的代码
    • 就从头到尾地执行了

图片描述

  • 这个函数可以调试么?🤔

改写

  • 我们改写一下代码

图片描述

  • 加上输出语句
    • 在调用函数前后
    • 在进入函数时、退出函数前
  • 尝试运行

运行结果

图片描述

  • 运行过程和你想象的一样么?
  • 这个应该怎么理解呢?

流程

图片描述

  • 前面只是定义函数并不执行

  • 主程序从第7行往下执行

  • 遇到sorry函数调用

  • 跳转到第1行

    • sorry函数定义的位置
    • 然后顺序执行sorry函数
    • 执行完成后跳转回调用程序的位置
  • 继续第9行

  • 然后程序全部执行完毕

  • 我们可以debug进去么?

debug

图片描述

  • 首先是定义函数

图片描述

  • 一开始没有定义的时候
  • 不认sorry函数
  • def之后
  • 就认了
  • 函数究竟是什么?

观察

  • 函数名也是一个对象的引用
  • 是一个function类对象的引用
  • 也有相应的地址

图片描述

  • 然后我们继续

继续

  • 一路n下去

图片描述

  • 在执行程序的时候
  • 把函数作为一个整体
  • 没有一步步地调试
  • 一次性把sorry()都执行完成了
  • 可以进入到函数内部一步步地执行么?

设置断点

图片描述

  • 但是这个断点好使么?

断点效果

  • 一路continue到断点

图片描述

  • 确实可以进入到sorry函数内部了
  • 但是走到第5句之后会如何呢?

跳出

  • 跳出函数
    • 注意那个return

图片描述

  • 第一个return是从sorry函数结束后
    • 从sorry函数中return出来
    • 回到主程序
  • 第二个return是主程序结束
    • 除此之外,还有什么关于函数跳转的命令么?

查看帮助

图片描述

  • 我们去试试

step

  • 当播放头运行到函数调用的这一句的时候

图片描述

  • step into
    • 进入了被调用的函数当中
    • 一步步调试执行
    • 那怎么知道我究竟在哪呢?

查询命令

  • bt和w(here) 都对应着print_stack_trace
    • w(here) 查询当前播放头所在位置
      • w可以告诉我,我在哪!!!
    • bt的意思是bottom 看的也是当前位置

图片描述

PrintStackTrace

图片描述

  • 这个就是函数堆栈的样子
  • 是一层层调用的关系
  • 怎么理解呢?

堆栈

图片描述

  • 这个堆栈总共分成四层(红、绿、蓝、紫)
  • 堆栈的顶在红色部分
    • 是sorry函数中第4行
    • 谁调用的sorry函数呢?
  • sorry.py中的第8行(绿色部分)
    • 调用了sorry函数
    • 谁调用的sorry.py呢?
  • exec(cmd,globals,locals)(蓝色部分)
    • 调用了sorry.py
    • 谁调用了exec函数呢?
  • bdb.py(580行)的run函数(紫色部分)
    • 是在堆栈(Stack)最底下
  • 函数就是这样层层调用的
    • step进去后可以进函数内部调试
    • 出了错也是一层层地找到位置
  • 比如
    • 我们打开一个不存在的文件的时候

出错提示

  • 明明只出了一个错误
    • 为什么给我这么多行提示?
    • 因为报错输出了跟踪(Traceback)的过程

图片描述

  • 错误发生在一个具体的位置
    • 是open函数的层层调用时候执行的一句
    • 离我们对于open函数的调用很远
    • 要一层层地跟踪(Traceback)
    • 找到我们代码的错误位置和类型
  • 调试的时候可以跳出函数么?

查询帮助

图片描述

  • r和return就是返回
    • 跳出当前函数
    • 返回到调用他的那一层
  • 试试

跳出函数return

图片描述

  • 红圈里面的r直接跳出函数 - r代表return
    • 把345句都执行完了
    • 然后返回到第9句的位置
    • 第9句跳出后返回到调用这个sorry.py的位置
  • 这样就可以
    • 深入函数
    • 跳出函数了
  • 我们可以从指令的角度观察一下吗?

反汇编

  • 指令分两大块

图片描述

  • 红色的是主程序
    • 0,6字节是函数sorry的声明(declaration)
    • 8,16字节是函数sorry调用
  • 黄色部分是sorry函数
    • 0,6字节是输出老婆我错了
    • 8,18字节是输出都是我不好
  • 虽然这个东西看起来很复杂
  • 但是对于我们来说很简单

定义函数、调用函数

图片描述

  • 就像灯装好了之后
  • 一拉灯绳
  • 就亮了

图片描述

  • 我们先去总结一下

总结

  • 这次我们调试了自己定义的函数sorry
  • 调试有这样一些命令
    • step
      • 跳入当前行所在函数
    • return
      • 跳出当前函数回到调用的位置
    • where
      • 告诉我现在执行到了哪里
      • 当前播放头的程序栈位置
  • 有了这样一些命令
  • 我们就可以更好地调试python程序了
  • 可以完成一些更复杂的套路么?🤔
  • 我们下次再说!👋

图片描述