好久没有编写逻辑如此复杂的函数了。用了一天的时间来思考代码实现,灵机一动,想出在构造树型结构的同时能够一边计算节点能量,没有完成它,成就感已经爆棚。设计方案非常的完美,但是实现的时候细节非常的多,还要考虑代码的扩展性,三个函数足足花了两天的时间来编写。等完成代码了,检查完最后一遍逻辑,满意的离开了实验室,睡了一个舒服觉,已经习惯性的留足精力来准备接下来的debug。
虽然早已经有心理准备,找BUG的时间远多于写代码的时间。但debug真的是非常煎熬。运行出现dll堆被破坏,显然是指针越界、数组越界引起。但内核和debug运行库除了提供segmentation fault,无法提供进一步的信息。已经熟悉透的逻辑只好一遍一遍重复跟踪,这种类型的错误必须保证头脑比编码时更清晰!
在渲染引擎这样的30w+行的C++代码中,折腾指针和数组的问题,让我进一步体会到,为何有如此多的人抱怨C/C++的机制。完全凭借人工排查错误,已经让我体力透支。显然这是一个最佳的学习时间,必须保持不断学习新技能的觉悟才能迈入更广阔的天地。
自己维护的渲染引擎有windows版本和linux版本,在windows上提供的内存检测工具基本都是付费软件,因为错误都一致,果断的选择了Linux下的开源软件:Valgrind。
Valgrind的手册非常详细,维护的频率也很高,支持的处理器架构较广。目标是快速的Debug,2014年都快结束了!所以,读完quick start就开始上马检测:
最后问题内存错误锁定在了一个底层的类函数和一个简单的循环语句上。循环语句已经在人工排错的时候加入了assert来排除越界的可能,而底层的类函数也不可能有错,只能是我使用的方式错了!同样也是灵光闪现,这个类是一个动态增加空间的容器,这让我回忆起曾经犯下的错误:保存了动态增长容器中的元素的地址!因为,一旦容器发生了动态增长,以前的元素全要“搬家”,地址也就失效。
检查容器的使用,果然为了方便使用指针的方式保存了地址。把指针更换为数组下标索引,bug解决!——2014.12.31
工具不是万能的,它只能给你提示。最终,还是依靠我们去排查问题,分析问题,解决问题!而要达到这一切,是建立在知识的储备上。
debug是一种预见还是遇见?是能预见还是只能遇见?