Technique to Read Source Code
Technique to Read Source Code
Excerpted from http://ruby-hacking-guide.github.io/intro.htm
Any programmer has to read a source code somewhere, but I guess there are not many occasions(机会) that someone teaches you the concrete ways how to read. Why? Does it mean you can naturally read a program if you can write a program?
But I can’t think reading the program written by other people is so easy. In the same way as writing programs, there must be techniques and theories in reading programs. And they are necessary. Therefore, I’d like to expand a general summary of an approach you need to take in reading a source code.
Principles
At first, I mention the principle.
Decide a goal
An important key to reading the source code is to set a concrete goal.
This is a word by the author of Ruby, Matsumoto. Indeed, his word is very convincing(有说服力的) for me. When the motivation is a spontaneous(自发的) idea “Maybe I should read a kernel, at least…”, you would get source code expanded or explanatory books ready on the desk. But not knowing what to do, the studies are to be left untouched. Haven’t you? On the other hand, when you have in mind “I’m sure there is a bug somewhere in this tool. I need to quickly fix it and make it work. Otherwise I will not be able to make the deadline…”, you will probably be able to fix the code in a blink, even if it’s written by someone else. Haven’t you?
The difference in these two cases is motivation you have. In order to know something, you at least have to know what you want to know. Therefore, the first step of all is to figure out what you want to know in explicit words.
However, of course this is not all needed to make it your own “technique”. Because “technique” needs to be a common method that anybody can make use of it by following it. In the following section, I will explain how to bring the first step into the landing place where you achieve the goal finally.
Visualising the goal
Now let us suppose that our final goal is set “Understand all about ruby”. This is certainly considered as “one set goal”, but apparently it will not be useful for reading the source code actually. It will not be a trigger of any concrete action. Therefore, your first job will be to drag down the vague(模糊的) goal to the level of a concrete thing.
Then how can we do it? The first way is thinking as if you are the person who wrote the program. You can utilize your knowledge in writing a program, in this case. For example, when you are reading a traditional “structured” programming (结构化编程) by somebody, you will analyze it hiring the strategies of structured programming too. That is, you will divide the target into pieces, little by little. If it is something circulating in a event loop such as a GUI program, first roughly(大概地) browse the event loop then try to find out the role of each event handler. Or, try to investigate(研究) the “M” of MVC (Model View Controller) first.
Second, it’s good to be aware of the method to analyze. Everybody might have certain analysis methods, but they are often done relying on experience or intuition(直觉). In what way can we read source codes well? Thinking about the way itself and being aware of it are crucially(至关地) important.
Well, what are such methods like? I will explain it in the next section.
Analysis methods
The methods to read source code can be roughly divided into two; one is a static method and the other is dynamic method. Static method is to read and analyze the source code without running the program. Dynamic method is to watch the actual behavior using tools like a debugger.
It’s better to start studying a program by dynamic analysis. That is because what you can see there is the “fact”. The results from static analysis, due to the fact of not running the program actually, may well be “prediction” to a greater or lesser extent(程度). If you want to know the truth, you should start from watching the fact.
Of course, you don’t know whether the results of dynamic analysis are the fact really. The debugger could run with a bug, or the CPU may not be working properly due to overheat. The conditions of your configuration could be wrong. However, the results of static analysis should at least be closer to the fact than dynamic analysis.
Dynamic analysis
Using the target program
You can’t start without the target program. First of all, you need to know in advance what the program is like, and what are expected behaviors.
Following the behavior using the debugger
If you want to see the paths of code execution and the data structure produced as a result, it’s quicker to look at the result by running the program actually than to emulate the behavior in your brain. In order to do so easily, use the debugger.
I would be more happy if the data structure at runtime can be seen as a picture, but unfortunately we can nearly scarcely(几乎没有) find a tool for that purpose (especially few tools are available for free). If it is about a snapshot of the comparatively(相对地) simpler structure, we might be able to write it out as a text and convert it to a picture by using a tool like graphviz (See doc/graphviz.html in the attached CD-ROM). But it’s very difficult to find a way for general purpose and real time analysis.
Tracer
You can use the tracer if you want to trace the procedures that code goes through. In case of C-language, there is a tool named ctrace. For tracing a system call, you can use tools like strace, truss, and ktrace.
Print everywhere
There is a word “printf debugging”. This method also works for analysis other than debugging. If you are watching the history of one variable, for example, it may be easier to understand to look at the dump of the result of the print statements embed(嵌入), than to track the variable with a debugger.
Modifying the code and running it
Say for example, in the place where it’s not easy to understand its behavior, just make a small change in some part of the code or a particular parameter and then re-run the program. Naturally it would change the behavior, thus you would be able to infer the meaning of the code from it.
It goes without saying, you should also have an original binary and do the same thing on both of them.
Static analysis
The importance of names
Static analysis is simply source code analysis. And source code analysis is really an analysis of names. File names, function names, variable names, type names, member names — A program is a bunch of names.
This may seem obvious because one of the most powerful tools for creating abstractions in programming is naming, but keeping this in mind will make reading much more efficient.
Also, we’d like to know about coding rules beforehand(事先) to some extent. For example, in C language, extern function often uses prefix to distinguish the type of functions. And in object-oriented programs, function names sometimes contain the information about where they belong to in prefixes, and it becomes valuable information (e.g. rb_str_length).
Reading documents
Sometimes a document describes the internal structure is included. Especially be careful of a file named HACKING etc.
Reading the directory structure
Looking at in what policy the directories are divided. Grasping the overview such as how the program is structured, and what the parts are.
Reading the file structure
While browsing (the names of) the functions, also looking at the policy of how the files are divided. You should pay attention to the file names because they are like comments whose lifetime is very long.
Additionally, if a file contains some modules in it, for each module the functions to compose it should be grouped together, so you can find out the module structure from the order of the functions.
Investigating abbreviations
As you encounter ambiguous(模棱两可的) abbreviations(缩写), make a list of them and investigate each of them as early as possible. For example, when it is written “GC”, things will be very different depending on whether it means “Garbage Collection” or “Graphic Context”.
Abbreviations for a program are generally made by the methods like taking the initial letters or dropping the vowels(元音). Especially, popular abbreviations in the fields of the target program are used unconditionally(无条件地), thus you should be familiar with them at an early stage(阶段).
Understanding data structure
If you find both data and code, you should first investigate the data structure. In other words, when exploring code in C, it’s better to start with header files. And in this case, let’s make the most of our imagination(想象力) from their filenames. For example, if you find frame.h
, it would probably be the stack frame definition.
Also, you can understand many things from the member names of a struct
and their types. For example, if you find the member next
, which points to its own type, then it will be a linked list. Similarly, when you find members such as parent
, children
, and sibling
, then it must be a tree structure. When prev
, it will be a stack.
Understanding the calling relationship between functions
After names, the next most important thing to understand is the relationships between functions. A tool to visualize the calling relationships is especially called a “call graph”, and this is very useful. For this, we’d like to utilize tools.
A text-based tool is sufficient(足够的), but it’s even better if a tool can generate diagrams(图表). However such tool is seldom available (especially few tools are for free). When I analyzed ruby to write this book, I wrote a small command language and a parser(解析器) in Ruby and generated diagrams half-automatically by passing the results to the tool named graphviz.
Reading functions
Reading how it works to be able to explain things done by the function concisely(简明地). It’s good to read it part by part as looking at the figure of the function relationships.
What is important when reading functions is not “what to read” but “what not to read”. The ease of reading is decided by how much we can cut out the codes. What should exactly be cut out? It is hard to understand without seeing the actual example, thus it will be explained in the main part.
Additionally, when you don’t like its coding style, you can convert it by using the tool like indent(缩进).
Experimenting by modifying it as you like
It’s a mystery of human body, when something is done using a lot of parts of your body, it can easily persist in your memory. I think the reason why not a few people prefer using manuscript(手写的) papers to a keyboard is not only they are just nostalgic(怀旧的) but such fact is also related.
Therefore, because merely(仅仅是) reading on a monitor is very ineffective to remember with our bodies, rewrite it while reading. This way often helps our bodies get used to the code relatively soon. If there are names or code you don’t like, rewrite them. If there’s a cryptic(神秘的) abbreviation, substitute (替代) it so that it would be no longer abbreviated.
However, it goes without saying but you should also keep the original source aside and check the original one when you think it does not make sense along the way. Otherwise, you would be wondering for hours because of a simple your own mistake. And since the purpose of rewriting is getting used to and not rewriting itself, please be careful not to be enthusiastic(热情的) very much.
Reading the history
A program often comes with a document which is about the history of changes. For example, if it is a software of GNU, there’s always a file named ChangeLog. This is the best resource to know about “the reason why the program is as it is”.
Alternatively, when a version control system like CVS or SCCS is used and you can access it, its utility value is higher than ChangeLog. Taking CVS as an example, cvs annotate
, which displays the place which modified a particular line, and cvs diff
, which takes difference from the specified version, and so on are convenient.
Moreover, in the case when there’s a mailing list or a news group for developers, you should get the archives(档案) so that you can search over them any time because often there’s the information about the exact reason of a certain change. Of course, if you can search online, it’s also sufficient.
The tools for static analysis
Since various tools are available for various purposes, I can’t describe them as a whole. But if I have to choose only one of them, I’d recommend global. The most attractive(有吸引力的) point is that its structure allows us to easily use it for the other purposes. For instance, gctags
, which comes with it, is actually a tool to create tag files, but you can use it to create a list of the function names contained in a file.
~/src/ruby % gctags class.c | awk '{print $1}'
SPECIAL_SINGLETON
SPECIAL_SINGLETON
clone_method
include_class_new
ins_methods_i
ins_methods_priv_i
ins_methods_prot_i
method_list
:
:
That said, but this is just a recommendation of this author, you as a reader can use whichever tool you like. But in that case, you should choose a tool equipped with at least the following features.
- list up the function names contained in a file
- find the location from a function name or a variable name (It’s more preferable if you can jump to the location)
- function cross-reference
Technique to Read Source Code的更多相关文章
- Tips for newbie to read source code
This post is first posted on my WeChat public account: GeekArtT Reading source code is always one bi ...
- 编程等宽字体Source Code Pro(转)
Source Code Pro - 最佳的免费编程字体之一!来自 Adobe 公司的开源等宽字体下载 每一位程序员都有一套自己喜爱的代码编辑器与编程字体,譬如我们之前就推荐过一款"神 ...
- How to build the Robotics Library from source code on Windows
The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...
- How to build windows azure PowerShell Source Code
Download any version source code of Windows Azure Powershell from https://github.com/Azure/azure-sdk ...
- akka cluster sharding source code 学习 (1/5) 替身模式
为了使一个项目支持集群,自己学习使用了 akka cluster 并在项目中实施了,从此,生活就变得有些痛苦.再配上 apache 做反向代理和负载均衡,debug 起来不要太酸爽.直到现在,我还对 ...
- view class source code with JAD plugin in Eclipse
The default class viewer doesn't decompile the class file so you cannot open and check the source co ...
- Classic Source Code Collected
收藏一些经典的源码,持续更新!!! 1.深度学习框架(Deep Learning Framework). A:Caffe (Convolutional Architecture for Fast Fe ...
- Attach source code to a Netbeans Library Wrapper Module
http://rubenlaguna.com/wp/2008/02/22/attach-source-code-to-a-netbeans-library-wrapper-module/ Attach ...
- convert source code files to pdf format in python
import os import sys def find_file(root_dir, type): dirs_pool = [root_dir] dest_pool = [] def scan_d ...
- Ununtu 12.04 gedit安装插件Source Code Browser
1. 安装ctags: sudo apt-get install exuberant-ctags 2. 打开https://github.com/Quixotix/gedit-source-code- ...
随机推荐
- Springboot使用基础总结
搭建项目 (Eclipse | | IDEA====>官方生成DEMO:http://start.spring.io/) 模版引擎 ( thymeleaf freemarker ...
- NET 6 实现滑动验证码(三)、接口
题外话,有网友说,这玩意根本很容易破解,确实是这样.但验证码这东西,就跟锁子很类似,防君子不防小人.验证码的发明其实是社会文明的退步.因为它阻碍了真正的使用者,却无法阻挡别有用心的人.但又有什么办法呢 ...
- Java基础知识篇【gitee】
https://snailclimb.gitee.io/javaguide 一.Java基本功 Java一次编译,字节码通过JVM,处处运行jsp会转化为servlet,也要由jdk编译OracleJ ...
- requests模块和openpyxl模块
第三方模块的下载和使用 1,第三方模块就是别人大神们已经写好的模块,功能特别强大.我们如果像使用第三方模块就先要进行下载.下载完成后 才可以在python中直接调用 2.下载方式一:pip工具 pip ...
- 关于JavaScript每句结尾是否需要添加分号问题
最近在学习JS的时候遇到这么一个问题.由于我之前的学习中一直是写一句JS代码,加一个分号.但是最近我才发现原来JS代码是可以不添加分号的.如果可以不写分号的话会不会更省事呢?于是我在网上查了相关资料整 ...
- 像go 一样 打造.NET 单文件应用程序的编译器项目bflat 发布 7.0版本
现代.NET和C#在低级/系统程序以及与C/C++/Rust等互操作方面的能力完全令各位刮目相看了,有人用C#开发的64位操作系统: GitHub - nifanfa/MOOS: C# x64 ope ...
- MAUI新生4.6-主题设置LightTheme&DarkTheme
通过主题设置,可以在运行时更改应用的主题外观,比如切换亮色主题和暗黑主题.主题设置并没有新的知识点,基本的原理如下: 定义每个应用主题的ResourceDictionary,每个ResourceDic ...
- 判断条件为NULL
在ASCII码表里NULL的二进制位0.所以NULL作为判断条件时,表示为假的意思. ASCII表 二进制 字符 ...
- [python] 基于matplotlib_venn实现维恩图的绘制
文章目录 VENN DIAGRAM(维恩图) 1. 具有2个分组的基本的维恩图 Venn diagram with 2 groups 2. 具有3个组的基本维恩图 Venn diagram with ...
- CVE-2016-4437
漏洞名称 Apache shiro 1.2.4反序列化漏洞(CVE-2016-4437) 利用条件 Apache Shiro <= 1.2.4 漏洞原理 Shiro提供了记住我(Remember ...