程序调试记录(纯自用)

本文记录了我在程序调试过程中的关键步骤和实用技巧,包括如何定位问题、使用调试工具以及解决问题的策略,旨在提升软件开发中的问题解决能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Stack类测试:
在测试Stck类型的变量内容是否正确时,经常会通过把所有值pop出来输出的方法,这样容易造成一个问题就是,栈已经被弄空了,以后再用的时候就会是一个空栈。所以,栈类型的变量测试完了以后及的把测试部分注释掉。或者查一下有没有好的方法用来测试栈

2017.11.15
//逻辑错误:版本v2,更改NodeRank类的rank方法,但是节点排名值得计算结果跟v1版本不一致,
//修改:map.put(i, t+0.4*nov(i,j)*map.get(i));===〉map.put(i, t+0.4*nov(i,j)*map.get(j));


开始考虑的是用queue存储最终的节点排名,把队列变量以参数的方式传输到finalRank()函数,这样先进先出后来用到映射过程中就可以
现在又想,就用ArrayList存储,按照value排名,然后下标从1开始遍历,得到跟queue一样的效果。

2017.11.18
今天需要处理两个图了,由于NodeRank类里面之前把g定义成了static,发现在main里面对g分别用两个图赋值,只按照最后一次赋值的来,而且啊,程序都需运行第一次赋值之后的rank方法。


code:


System.out.println("这是第一个start");
NodeRank.g=g2;


rank=NodeRank.rank();
System.out.println("这是第一个rank");
NodeRank.g=g;
rank2=NodeRank.rank();
System.out.println("这是第二个rank");


result:


这是第一个start
这是第一个rank
这是第二个rank
排名结果:2--0.3479683489497371
排名结果:0--0.28652638523658425
排名结果:1--0.20537981498161176




处理:只能是把g定义成普通的,然后再用构造函数初始化g,这样对于不同的图就有了相应的rank类。
注意-----后来发现,我的测试输出可能是有问题的,所以上面说的g是static时候只按照第二次赋值的说法可能有误,记住退回到v2版本去看看到底是不是只按照最后一次赋值的处理,在v2中,g还是static。由于发现把g定义成非静态处理以后似乎更好所以没有退回去检测。再后来,我发现好像只需要给一个图排序,也就是VNR的图,现在想想弄成静态的也可以,再再后来,又想,是要有多个VNR的,哎哟,问题好像更多了呢。


问题:测试的时候发现,会映射到重复的节点上。
解决:对于物理网络节点,添加一个标志位,已经被映射过的就干脆因为不符合要求而直接不被加入备选项中。这个标志位对于一个网络请求的所有节点映射过程中起作用的,所以要声明在遍历VNR节点之前。


主动排查发现:sim这个数组,对于一个VNR中的每一个节点都要进行一次更新,所以一定一定要声明在里面,(代码中有一个声明被注释掉了,可以注意下),这样上次节点的结果才不会影响这次的。


结果不理想,排查发现:一个超级大的逻辑错误,我的方法里面,只传入了物理网络而没有虚拟网络,关于虚拟网络只是传入了节点下标和排名值,但是我在方法内部,同时需要获得物理网络cpu和虚拟网络cpu,在我想要虚拟网络cpu的时候,我是用物理网络拓扑的g,还有虚拟网络拓扑的节点下标去查的,这个根本没有任何含义!!傻子傻子傻子!!!
解决:给方法添加一个参数,传递进去虚拟网络拓扑咯。总感觉还有别的办法,但是哪个更好却不知道了。


2017.11.19(main和embedding方法)
语法问题:方法需要Map类型的变量,传入LinkedHashMap型的提出语法错误。声明和创建的时候都用的LinkedHashMap不行,但是声明用map,初始化用linkedhashmap就行。
上面说错了,其实是,方法返回一个map型的,我要赋值给一个linkedhashmap的变量l,l被声明成map,初始化成linkedhashmap的时候没毛病,但是声明并初始化成linkedhashmap的时候不行。


2017.11.21(Floyd方法)
问题:在floyd算法里面,把路径入栈再出栈的时候,用的for循环,终止条件是(i<stack.size()),然后在循环里面出栈。一直出问题,忽略了出栈后size是会变得,所以每次测试i的时候,size都不一样
改正:如果还是用for循环的话,就需要把初始时候的size存储,然后再用做循环终止条件。后来没有用for,而是改用while,在栈非空的时候执行循环。所以对栈来说,似乎while循环更合适一点儿。


大改embedding类,EmbedOrder类,
其中embedorder类,更改了返回类型为link<Map>//






2017.11.22
Floyd.java
在后面的编程中发现,我需要知道floyd计算后整条路径的权重以及这条路径(先计算路径权值,如果权值较小,再去记录路径),所以这一个算法对我来说需要返回两类值:路径list,还有路径权重,临时为了更改方便,决定加入
int[][]用来存储路径权重//这里一定一定要好好改改,待改进

embedding方法,需要返回两类值,节点间的对应关系以及链路间的对应关系。现在打算用返回类型返回节点间的对应关系,用参数引用的方式返回链路间的对应关系。后期的改进中,要把这两类数值存储到txt里面,如果是一个txt的话,一行内容,表示 虚拟起始、虚拟终止、物理起始、物理终止、物理路径




2017.11.23
启发:
如果想要在一个方法里面返回多种数据,可以考虑把结果写成一个数据类型啊,里面的成员变量就是你要的多个结果

感受:初期留下的“小将就”,在后面都是“大麻烦”,教训教训啊!!!

2017.11.24
经验:什么样的变量没有被初始化才会被报错?
An:如果,你的变量定义了,没有初始值,后面首次用它是为了给他赋值,也就是在等号的左边,那么就没关系
但是如果你没有给他初值,而且还没有让他被赋值,就开始让他作为方法参数或者放在等号右边,那么就会报错。一种情况,即使你赋值了,如果没有跟后面用到的地方在一个代码块里,有可能也报错,比如,在if==0的时候赋值,在if==1的时候使用变量,就会报错。变量一旦被放入if里面再赋值的话,除非所有的if都有赋值语句,不然在if外面用的话就会被报错。
局部变量要先给赋初值才能进行使用,成员变量可以不赋初值,它有默认值,但是局部变量在声明的时候最好给赋初值。要不会出现编译错误
,JAVA局部变量都必须给初始值的
下面例子


for(Map.Entry<Integer, Double>e:embOrder.entrySet()) {
int firstSel;//用于存储第一个VNR节点对应的物理节点
int lastSel;//用于存储上一个VNR节点对应的物理节点
List<Integer> pathSel;//某对被选中的节点最终被选中的路径
int pathLength=5000;//用于存储对应的物理路径的长度,待改进,这里的;路径长度选的是长度上线,直接用5000不好

boolean[] fTemp=new boolean[pn.getNumOfNode()];//用于标志这个节点在回退过程中,有么有被映射过
if(t==0) {
entryFirst=e;
}
if(t==1) {
entry=e;
int firsTemp;//用于临时存储第一个虚拟节点某次被选中的物理节点
int lasTemp;//用于临时存储某个虚拟节点被临时选中的物理节点
List<Integer> pathTemp=new LinkedList<Integer>();//用于存储被临时选中的路径;

for(int j=0;j<3;j++){

{
double[] sim=new double[pn.getNumOfNode()];//待改进:这里不好。这个数组肯定用不到这么大,++但是,每个i都有可能被记录,所以用这么大的数组是可以的。
for(int i=0;i<pn.getNumOfNode();i++){
if(!f[i] && pn.getCpu(i)>=vn.getCpu(entryFirst.getKey())){//物理网络节点cpu大于VNR节点cpu
System.out.println("embedding__new__待映射点1与物理节点中满足要求的节点"+i+"的相似度:"+Similarity.cos(vn.getNode(entryFirst.getKey()),pn.getNode(i)));
sim[i]=Similarity.cos(vn.getNode(entryFirst.getKey()),pn.getNode(i));
// g.getCpu(i)>g.getCpu(entryFirst.getKey()))
}
}
firsTemp=ProbabilitySelected.proSelected(sim);
fTemp[firsTemp]=true;
System.out.println("此次选中节点"+firsTemp);
}
/*启发:这里用了两个程序块,因为一个待映射节点对应一个sim数组,这个数组在存储的时候我是用节点下标作为数组下标的,为了不让上一次被允许的几点的sim值影响下一个节点的值,
* 所以sim这个数组,对于每一个待映射节点 都需要从空的数组开始,可以每次用之前更新赋值为0,但是我选择了使用俩程序块,在每个块里定义数组,这样更新,*/
{
double[] sim=new double[pn.getNumOfNode()];//待改进:这里不好。这个数组肯定用不到这么大,++但是,每个i都有可能被记录,所以用这么大的数组是可以的。
for(int i=0;i<pn.getNumOfNode();i++){
if(!fTemp[i] && !f[i] && pn.getCpu(i)>=vn.getCpu(entry.getKey())){//物理网络节点cpu大于VNR节点cpu
System.out.println("embedding__new__待映射点2与物理节点中满足要求的节点"+i+"的相似度:"+Similarity.cos(vn.getNode(entry.getKey()),pn.getNode(i)));
sim[i]=Similarity.cos(vn.getNode(entry.getKey()),pn.getNode(i));
// g.getCpu(i)>g.getCpu(entry.getKey()))
}
}
lasTemp=ProbabilitySelected.proSelected(sim);
System.out.println("此次选中节点:"+lasTemp);
}

if(pathLength>Floyd.floyd(pn, firsTemp, lasTemp, pathTemp)) {//如果新得到的路径长度小,那么就存储这个新的路径对应的起始终止节点,以及路径
pathLength=Floyd.floyd(pn, firsTemp, lasTemp, pathTemp);
firstSel=firsTemp;
lastSel=lasTemp;
pathSel=pathTemp;
}

/*在这里就可以把映射结果加入到map里面啦*/
emb.put(entryFirst.getKey(), firstSel);
emb.put(entry.getKey(), lastSel);
}


}

}










经验:关于变量定义的位置,
他会影响循环的次数,在循环中还会影响是不是能把前面得到的值传递给后面,如果想传递,一定要定义到循环的外面。

又是一个变量定义位置影响运行结果的错误案例
41、42行和74、75行
package vnr.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import vnr.bandit.Embedding;
import vnr.graph.CreateGraph;
import vnr.graph.Edge;
import vnr.graph.Graph;
import vnr.graph.Node;
import vnr.rank.EmbedOrder;
import vnr.rank.NodeRank;

public class embedThread implements Runnable {

	String folder;
	Graph gPhy;

	/**
	 * @param folderName 存储VNR的文件夹
	 * @param g 待映射的物理网络拓扑
	 * */
	public embedThread(String folderName,Graph g) {
		// TODO Auto-generated constructor stub
		folder=folderName;
		gPhy=g;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		int nodeNumPhy=-1,edgeNumPhy=-1;
		int nodeNumVir=-1,edgeNumVir=-1;//改进:这里好像用不到两个变量,物理网络和虚拟网络可以用同一对变量。
//		LinkedHashMap<Integer,Double> embOrder =new LinkedHashMap<Integer,Double>();//最终映射顺序
//		LinkedHashMap<Integer,Integer> result=new LinkedHashMap<Integer,Integer>();
		
		int sucCount=0;
		int failCount=0;
		
		try {
//			BufferedReader phyReader=new BufferedReader(new FileReader("sub.txt"));
			Embedding embeder = new Embedding(".\\Result");
			
			String line;
			String regex=" ";
			String[] lineContent;
			List<String> lines=new LinkedList<String>();
			
			/*虚拟网络相关变量*/
			Edge[] edgeVir=null;
			Node[] nodeVir=null;
			Graph gVir=null;
			
			//网络映射相关变量:noderank
			List<Map.Entry<Integer,Double>> rank=new ArrayList<Map.Entry<Integer,Double>>();//VNR
			

			
			/*虚拟网络topo处理,把表示虚拟网络拓扑的文件存为Graph*/
			File demo = new File(folder);
			File[] vnrs=demo.listFiles();
			
			for(int j=0;j<vnrs.length;j++) {
				BufferedReader virReader = new BufferedReader(new InputStreamReader(new FileInputStream(vnrs[j])));
				
				
				LinkedHashMap<Integer,Double> embOrder =new LinkedHashMap<Integer,Double>();//最终映射顺序
				LinkedHashMap<Integer,Integer> result=new LinkedHashMap<Integer,Integer>();
				//启发:本来这两个变量的定义是在上面,但是运行的时候出现数组越界异常,debug发现result的似乎不太对,所以怀疑是前面对变量的赋值影响了后面
				//试图调整变量定义的位置,使得每个虚拟网络请求都有自己的排序变量,所以放到for里面创建,果然不再出现异常
				
				
				lines.clear();
				while((line=virReader.readLine())!=null) {
					lines.add(line);
				}
				
				for(int i=0;i<lines.size();i++) {
					lineContent=lines.get(i).split(regex);
					if(lineContent.length==2) {
						nodeNumVir=Integer.parseInt(lineContent[0]);
						edgeNumVir=Integer.parseInt(lineContent[1]);
						
						edgeVir=new Edge[edgeNumVir];
						nodeVir=new Node[nodeNumVir];
						gVir=new Graph(nodeNumVir);
					}else if(lineContent.length==1) {
						nodeVir[i-1]=new Node(Double.parseDouble(lineContent[0]));
					}else {
						edgeVir[i-1-nodeNumVir]=new Edge(Integer.parseInt(lineContent[0]),Integer.parseInt(lineContent[1]),
								Double.parseDouble(lineContent[2]));
					}	
				}
				CreateGraph.create(gVir, nodeVir, nodeNumVir, edgeVir, edgeNumVir);
				
				/*计算节点排名以及映射顺序*/
				NodeRank nr=new NodeRank(gVir);
				rank=nr.rank();
				for(int u=0;u<rank.size();u++) {
					System.out.println(rank.get(u).getKey()+"-"+rank.get(u).getValue());
				}
				
				embOrder=EmbedOrder.embOrder(rank,gVir);
				/*节点映射+链路映射*/
				
				switch (embeder.embedding(embOrder, result, gVir, gPhy,j)) {
				case 1://节点映射成功则进行链路映射
					switch (embeder.embLink(gVir, gPhy, result,j)) {
					case 1://链路映射成功
						sucCount++;
						break;
					case -1://等待补充:映射失败后除了统计失败数量,还需要把被这个失败映射占用的资源恢复回来
						failCount++;
						break;
					default:
						break;
					}
					break;
				case -1://等待补充:映射失败后除了统计失败数量,还需要把被这个失败映射占用的资源恢复回来
					failCount++;
				default:
					break;
				}
				

				System.out.println("成功映射数目:"+sucCount);
				System.out.println("失败映射数目:"+failCount);
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("FROM embedThread.java-"+e);
		}
	}

}

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值