在开发游戏的过程中有许多问题,这里只挑出几个说明。
- 迷宫游戏部分完成后,设置迷宫的大小后,迷宫生成的很慢?
- 由于迷宫生成过程中存在大量的for循环,导致速度变慢。优化代码结构,减少for循环的次数后,速度变快。
- 加入《魔塔》游戏机制的过程中,每次进入下一层或者上一层地牢,地图每次都会刷新,不能保存上一次玩家对地牢的操作?
- 采用堆上三维数组的方法,问题轻松解决。
- 在实现两层地图,以及切换地图的过程中,人物位置的初始化,在这个过程中出现了程序崩溃的问题,使用QT调试,一步步跟踪问题出现的位置,解决不了?
- 经检查发现是因为三维数组越界了,但是使用QT调试时,显示出现问题的地方,却不是真正出现问题的位置,查明原因后,又积累了调试的经验。
- 小怪的动态效果实现?
- 用一个定时器,每500ms刷新一次,显示小怪的窗口,每次刷新时都让其切换显示图片,让每次切换的图片具有连贯性,就能在不断的切换中实现动态效果。
- 服务器生成的地牢字符串,客户端接收不完整?
- 经过不断的调试后发现,原因是TCP传输中,当传输的数据量较大时,不会一次RTT就把所有的信息传输完毕,而是需要经过多次RTT才能传输完成。而原来客户端的代码逻辑是从服务器一接收到数据就开始处理,对于数据较大的情况,可能没接收到完整的数据就开始处理了,这样就会出错。
- 改进的方法是:服务器发送给客户端的消息都会加一个Head,用来指示传递的消息长度。这样,客户端第一次接收到数据时,就会去获取到整个消息的长度,只要当前接收的数据长度没有到达Head指示的大小就一直等待接收消息,直到接收到完整的消息,才会开始进行处理。
- 两名用户同屏操作时,可能会有多个请求同时到达服务器,这时服务器不能正常响应请求?
- 解决办法是:客户端的请求都加上一个终止标志位,服务器在接收到一长串请求消息时,根据这个终止位来拆分不同的请求,将这些请求消息存放到一个容器中,最后,再从容器中依次取出请求消息来做出响应。
- 长时间(1天以上)不连接服务器,再次连接,服务器会发生崩溃?
- 通过生成core dump文件,运用gdb调试core dump文件,发现崩溃的原因是程序收到了SIGSEGV信号,出错的位置在mysql_fetch_row ()函数调用时,发现是在mysql_query()函数执行出错时,调用mysql_store_result()会返回NULL,此时再调用mysql_fetch_row ()就会发生段错误。然后,又考虑为什么只有1天后再次连接服务器会报错,重启服务器后,再次连接一切正常?最后,考虑到可能是mysql有超时机制,长时间没有查询请求后,会自动关闭连接,结果在网上一搜真的是这样:Mysql默认连接超时时长为8小时,无查询请求8小时后,Mysql会自动关闭连接,此时再调用mysql_query()函数,就会执行失败
- 解决办法有两种:第一种是,修改Mysql配置文件,将超时时长设置为最大值31536000s=1年,但这种解决方法并不完美,终究会超时。第二种解决方法是,在调用mysql_query()函数失败时,如果失败返回的错误码为CR_SERVER_LOST,则代表服务器不可用,Mysql服务器断开了超时的连接,此时再调用mysql_real_connect()重连一下Mysql服务器,再执行查询,就能查询成功了
- 测试过程中发现,不能支持多个玩家同时匹配游戏,服务器存在崩溃以及内存泄漏的问题?
- 通过调试core dump文件发现,崩溃的原因是内存用完,出现bad_alloc异常,发生在splitRequestMsg函数中。最开始,认为是存放客户端请求信息的RqMsgList数组,在处理完消息后,没有释放内存导致的,结果在每次处理完毕后,调用shrink_to_fit,也不能解决崩溃问题,后来又考虑是不是vector分配内存时两倍扩容的机制导致的问题,把vector换成了deque,也没有解决问题。最后考虑可能存在死循环,让RqMsgList一直在申请内存,导致内存用完,最后发现在拆分请求字符串时确实存在死循环的可能,修改后,bad_alloc异常不再出现
- 虽然服务器不会出现bad_alloc异常而崩溃了,但是在测试的过程中,却发现了内存泄漏问题。每次测试200左右房间数的对战,内存总是会被占用2M左右,而且在服务器处理完毕后,也不会释放。最开始考虑到,可能是在堆上申请内存的对象,在使用完毕后,没有释放内存导致的,但是一行行检查代码时,没有发现这个问题。后来想借助内存泄漏检查工具valgrind来检测内存泄漏的位置,但是valgrind不支持muduo库的一些语法,不能检测。然后,就想着在请求信息处理函数onMessage中,一行行的注释,每次去掉一些功能,去掉一些处理的逻辑,再测试看有没有内存泄漏的现象。因为内存泄漏发生的很快,也很容易出现,所以就定位到问题出在编解码器的处理函数deCodeMessage中,在deCodeMessage中用相同的办法,定位到了Mysql类中的Register函数,在Register函数中用相同的办法,终于定位到了内存泄漏的罪魁祸首-mysql_store_result与mysql_free_result,当保存了查询结果后,必须释放,不然mysql申请的用来保存结果的内存就不能被释放,也不能被再次使用,从而导致内存泄漏。定位到这个问题后,发现之前写的代码中,很多函数都有类似的问题,修改后,内存泄漏问题解决了。