这就开始实现前面说的局部对if-else分支、循环块的局部插桩了
其实思想很简单,只不过大家书写代码的方式千差万别,所以要考虑的情况还是蛮多的
一、if-else分支(桩=输出当前行)
1. if/else/else if(...) ...
2. if/else/else if(...) {...}
1、2插桩需变成:if/else/else if(...) { 桩 ...}
3.if/else/else if(...){
.... (在此处插桩即可)
}
4.if/else/else if(...)
{
... (在此处插桩即可)
}
5.if/else/else if(...)
...
6.if/else/else if(...)
{....}
5、6插桩需变成:
if/else/else if(...)
{ 桩 ....}
插桩总共需要考虑这6种情形,但是代码中有一些可以合并的
二、循环结构
1.for/while结构
(1)for/while(...) ...
(2)for/while(...) {...}
(1)/(2)插桩变成:
int cnt;
for/while(...) {cnt++; ... }
printf("%d\n",cnt); (相当于要插三句桩,比if-else复杂一些)
(3)-(6)和上面相似,不一一列出来
2.do while结构
(1) do{
...
}while(...);
(2) do
{
...
}while(...);
(3)do
{...
}
while();
这种情况注意下:不是在遇到}后插输出语句,而是在while语句后
do-while结构好的一点就是应该不会出现那种单行的无{}语句,遇到do之后只需要在后面找有while()的一行就可
三、多重循环
一开始我只考虑了前两块情况,没有注意到可能出现多重循环的可能,譬如:
int cnt1 = 0;
for(int i=0; i<n; i++){
cnt1++;
int cnt2 = 0;
while(a){
cnt2++;
}
output1(cnt2);
}
output2(cnt1);
这种情况要插入两个输出语句的桩,但是在检验循环语句的时候,先查到for循环,则output2会先被赋值为output,然后output1会覆盖output2的值成为output,所以应该输出output2的地方就输出不了,插桩失败。
后来我的解决方式是在repeat_flag的基础上又设置了一个double_repeat_flag
当double_repeat_flag为true时,重新设置一个output2,此时不会被覆盖,能正确输出
不足是只能解决双重循环的问题。其实实现三重循环思路应该也差不多,但是有点麻烦,我不太愿意写了..先这样吧
补充:在实现后续操作过程中,发现双重循环的这种插桩方式对cnt2的总次数很难以利用和统计,故需要对以上操作进行更改
int cnt1 = 0;
int sum = 0;
for(int i=0; i<n; i++){
cnt1++;
int cnt2 = 0;
while(a){
sum+=1;
}
}
output1(sum); //放在外面比较好,不然会输出多次,这个暂时还没实现
output2(cnt1);
一想到在过一遍代码时还要考虑这么多复杂的情况就头大,事在人为,加油吧!