Skip to main content

NJU PA1 回顾

因为第一次答辩没过,痛定思痛,想了想原因主要有两个

1.主要是因为pa1的代码我有点忘了,当时是10月份写完的

2.当时做pa是闲的没事,也没听过ysyx项目,想着做出来能用就行,所以做得比较草率。

当然,还是因为没有做好。

我的记忆不太好,所以就有了这篇博客,帮助记忆我的回顾过程,顺便督促自己在下次答辩前能改掉一些bug

一,首先是“优雅的退出”

哎,明明我实现了,可是因为太紧张以及实在有点忘记了导致我自己说自己没实现555。现在回顾一下我之前写的代码step by step,首先从键入q开始

会返回-1到这里

在sdb这个循环中,检测到返回值是-1,就会返回到main函数里面,下一步就是从main函数返回,返回值是is_exit_status_bad()函数的返回值

good检测到nemu的状态两种情况会return 1(错误返回),第一种是检测到END并且halt_ret ==0,去看一下什么时候会出现这种情况

在HIT GOOD TRAP时,nemu的状态就是这个,所以我之前的优雅的退出其实实现错了!!哎,所以没通过也很正常,我应该让键入q时,nemu的状态变为QUIT,而不应该改return good,改正如下

这样键入q时,good绝对为1,return !good,就可以正常退出了

我之前不太明白为什么是这两个条件,现在回顾一下终于懂了

1.第一个条件是为了在pa2一键运行的时候起作用的,因为那时候退出不是通过键入q,而是直接运行的

2.第二个条件就是键入q时退出

ok,“优雅的退出”结束,这次肯定不会有问题了。


二,表达式求值

这里我因为不会怎么运行测试用例,所以助教老师直接让我把之前的测试用例拿出一个去测试运行了,结果nemu卡住了,事后,我去看了一下本身表达式有问题

抽到的表达式正好是除零的,虽然有点衰,但是也暴露了几个问题

1.我的nemu对于除零以及其他的一些错误没有反应而只是被卡住了

2.生成测试代码的程序生成了除零代码

3.我的nemu的表达式求值功能确实没有经过测试,未测试的代码都是错的

针对这三个问题,我将做出以下改正

1.让nemu对于某些异常情况能作出反应

2.改进生成测试用例的代码,保证其不生成奇奇怪怪的错误表达式

3.用其测试我的表达式求值的过程

(其实我在答辩前就知道我存在这么些问题,但感觉改正好麻烦,想着抱着侥幸心理,结果….哎,还是得认真一点比较好)

1.让nemu对于某些异常情况能作出反应

实现如下

再次运行 p (((9+(((((((4))/((((0)-8+(4)2)))(19/1(4)-8/(1)))))))))*5)这个巨大的表达式

所以我感觉我的表达式求值 (其实)( 应该)( 或许)( 大概) 没什么问题,毕竟也确实检测出了除零错误,但是还是应该运行更多的测试用例进一步测试。

2.改进生成测试用例的代码,保证其不生成奇奇怪怪的错误表达式

除零是我现在想到的唯一奇怪表达式(之后我又想到一个,就是生成超长表达式(超过容纳其的空间),但是这个会在生成的时候报段错误,导致生成不了input文件,多次运行总有一次可行的,我就没管了)

这是我之前生成的测试用例的其中两个,第二个就是一个除零错误,发现第二个前面的正确答案竟是上一个的,说明还是有点bug,接下来就要保证不会生成这种除零的错误了。

之前除零生成时只会报warning,这就导致了接下来都是正常的,我只需要在其生成除零表达式时将warning当成error,让其无法返回值到ret中,他就会continue,也就解决了生成除零表达式的错误

3.用其测试我的表达式求值的过程

改造如下

试了几组都没有问题,以下是某次的截图

我觉得我的表达式应该是没什么问题了

三,扩展表达式求值的功能

助教老师还没有问到这一步我就被pass了呜呜呜

好像讲义上并没有要求用测试脚本去测试扩展的几个功能哎

所以我直接手动运行了几个测试用例,测了一测都没啥问题好像

我的*取值会取这个地址开始的4个字节,并将其转化为十进制(因为我也不知道*取值要取几个,我就按我自己的想法了,并且我的转换是按照低地址是低位来转换的(小端序))代码如下

四,实现监视点

我没有对我的监视点代码进行过测试,但是讲义上说可以边用边测,比较符合我的习惯,我比较懒,并且我学习也都是边实践边学习的,我觉得这样效率高一点。

以下我开始revise一遍我写的代码,防止下次答辩我又忘得一干二净了

第一个是我的wp的结构,后三个是在sdb里面使用监视点的函数,分别是创建,删除,打印。最后一个是在运行时的检测(检测是否需要停止执行)

可以看到这三个函数调用了一些接口,分别是:new_wp(),show_w(),del_w(),check_w()。下面看一下其具体实现

上图是new_wp()的实现,是在free_链表中请求一个wp,现解释:

1.首先暂存free_和head的值

2.让free_指向下一个空闲链表,空出一个给我使用

3.接下来对head是不是空进行分类讨论,是空就直接赋值,不空就遍历到最后一个再赋值(其实回头再看我好像可以把两者合并,但我不想改了,毕竟害怕改了又出bug,能跑就行)。最后返回,在上层函数进一步赋值。

上述是check_w()的实现,就是在循环中逐个求表达式的值并与原值对比,不相等就返回不相等的那个编号(为了在上面能知道是哪个被触发了)

上述是show_w的实现,就是遍历链表,打印 1.编号 2.表达式 3.表达式的值 4.如果不是最后一个,还要打印下一个的编号(方便调试)

上述是del_w的实现,主要是通过编号找到要删除的监视点,把该监视点传给free_wp()函数,再打印一条删除消息,这里使用了free_wp()函数,下面是其实现

因为是单向链表,所以我一开始定义了两个指针,last2指针在遍历时会慢一个身位,然后也是分是不是要删除第一个监视点来讨论,之后把其他编号大于它的减一,最后把释放的放入free_中。

OK,这就回顾完了,我记得当时做的时候出过很多bug,因为当时是我第一次写链表。

对了,我没有实现断点功能,因为断点可以通过$pc == ?来实现。

后面好像就没有什么必做题了

完结撒花。(希望能过答辩)

过啦