之前一股脑往前做的时候并没有考虑到大体方向的问题,直到一些问题暴露出来:
1.malloc calloc返回的一定是指针,而不是普通的数据类型
这就意味着对对象的读写只可能是通过*、->、[]三种符号来完成
2.静态的代码分析方式
非运行时方式,意味着if else分支不知道进入哪个,while等循环语句也不知道循环多少次
昨天和张博讨论的说法是,这个东西很难做成一个运行时,最后讨论出来的做法是在源代码基础上只要上一句访问了对象下一句就插个桩,譬如一条输出语句。不好的地方在于开销会特别大,输出语句会特别多,而且对输出语句再做统计也不方便。
后来又请教了段师兄,他提供了一种思路,首先先把if-else while等语句识别出来,如果括号内是单纯的值判断,就在前面的代码中追踪他的值的改变(可能与输入值有关、与前面复杂操作有关、while等循环还与while语句段内的操作有关)。另外,如果是判断某某不为空情况就比较复杂,师兄比较忙,让我自己先想想。我认为这种做法也十分复杂,即使是值判断,首先需要把前面对值的操作记录下来(而且Java内还很不方便模拟C提取的字符串代码)。而且尤其遇到while循环的时候,这个值每次可能还在变化,每循环一次就要追踪一次,如果循环100次可以说是很麻烦的了。
综合两位师兄提的一些思路,我认为现在有两条路可以走:
(1)局部插桩,对if-else while等代码段进行输出语句插桩(比如if-else用输出enter,while用计数器)。
要单独写一个对if-else while等代码段内正则匹配程序,提前记录下来走的分支(譬如对语句行标注true 和false)和每个while循环的次数(可以做成一个顺序数组,依次存放每次while循环的计数值,再由Java依次读取)
纯if语句 只有进或不进 譬如用0 1表示
if-else语句 n个分支中只能走一个分支 譬如用1-n之间一个数字表示
相当于也要做成一个key-value对,key是if else出现的序号
关键在于对运行结果的统计是不是手动的。。。好像没有自动化的方式呀。
(2)C与Java的交互
上次简单看了一下,有个工具来实现,还需要编译什么的,感觉很麻烦,就没有细看,这个作为备胎吧
3.对象同名问题
对象同名是由对象生命周期不同而出现在不同的命名空间里
譬如function1里有一个数组a被malloc了,function2里也有一个数组a被malloc了,它们实际上是两个对象
解决这个问题的方法是记录下当前命名空间的path,可以理解为函数名
问题来了,在function1里,如果前半段一个数组a被malloc了然后free掉,紧接着又malloc一个数组a,这是完全可行的把,这就意味着命名空间绝对不是主键。
一个对象被读写的区域只可能是当前命名空间内malloc之后free之前的语句。
但是指针可能通过函数参数的方式传入到别的命名空间中,虽然跨越了命名空间,但实际上他们指向同一块内存。
这里有个可能就是如果它在其他命名空间内换了名字(其实就是第4点里讨论的第二种名字)
4.不同名指向同一内存区域的问题
一种情况可能是:function2内{ ... *p = malloc(); ... return p;} function1 { *pp = function1(); }
其中:function1调用function2
还有情况可能是 function1内 {... int *p = malloc(); function2(p); ... }
function2(int *pp){ 对指针pp的操作;}
还有一种情况是:hash_entry_t* e = h->array[i]; (h->array = (hash_entry_t** )calloc(...);)
它实际上算是h->array指向内存的一部分