一场由数据类型引发的灾难

程序员最讨厌的两件事:给代码写注释,读没有注释的代码

(ง •̀_•́)ง┻━┻掀桌

背景

事情的起因是做大数据系统这门课的作业,其中要用到老师自己写的一个开源同步图计算系统Graphlite。所以免不了要读陌生的代码。 怎么说呢,老师给代码的注释也就满足刚刚能使用……对于很多细节的东西就没了说明。 例如,代码里有很多封装好的函数倒是说明了功能,但对更细节的东西像数据类型的选择之类的,则没有说明。 毕竟是个人项目,没有完善的文档也可以理解……

噩梦的开始

我一开始太大意了。因为这个作业目的就是在原有例程的基础上修改,来实现自己的功能。 但坑人的地方在于老师没说哪里不能改。 所以我就按照自己的需求把代码里定义好的函数的的数据类型修改了。 OK,下面开始进入噩梦。

噩梦

首先是运行超时,怎么也跑不出结果。

不过这个难不倒我,经过多次试验后发现是修改了关键代码处数据类型的问题,改回来后就可以运行。 但是改回来的只是被我修改的众多数据类型的一部分。

虽然程序能运行了,但是却又停不下来了……也就是说终止条件设置的有问题。

设计的是从aggregator读取当前超步的全局变量,即误差,若误差为0则停止。但坏就坏在了我将这个变量强行从double型变成了int型:

int global_val = *(int*)getAggrGlobal(0);

我把一个按double型存储的数据,强行用int型的格式读取了出来,那么读出来的值自然是不对的。

至于为什么最后给改过来了,是因为发现可能是数据类型的问题,索性就将所有擅自修改过的数据类型都改了回来……真是瞎猫碰上死耗子

(我觉得有必要专门研究下数据类型转换……)

让我发现是数据类型出了问题的突破口是这里:

value_int = (int)value; 
int n = sprintf(s, "%lld: %d\n", (unsigned long long)vid, value_int); 

这是改正后的代码,而改正前是:

int n = sprintf(s, "%lld: %d\n", (unsigned long long)vid, value); 

也就是说,我强行将一个double型数据按照整型数据的格式打印了出来!

就是这个困扰了我一天的问题!莫名打印出设定范围之外的数。

最后是在打印另一个变量观察输出时才发现了端倪。找到了问题所在,就乖乖的把数据类型都改了回去,顺利解决作业……

事实证明,printf才是最强的debug工具……

黎明

现在回过头来看,这个作业本应该昨天就搞定的,但在我观察到奇怪的输出值后却并没有认真思考原因。

事实上,每次编译时,编译器已经就那个出错的地方给了我warning,但由于我经历过太多无足轻重的warning,所以不由自主地忽略了这一信息。

所以这次的教训值得吸取,没有这一天时间的浪费,我也意识不到是这里出了问题。

还是要经历过之后才有长进。