您必须已经从标题中猜到,今天的文章将关注软件源代码中的错误。但不仅如此。如果您不仅对C ++感兴趣并且在阅读其他开发人员代码中的错误,还会挖掘不寻常的视频游戏并想知道“roguelikes”是什么以及如何玩它们,那么欢迎继续阅读!
在寻找不寻常的游戏时,我偶然发现了大灾变黑暗日子,由于它的图形基于黑色背景上排列的各种颜色的ASCII字符,因此在其他游戏中脱颖而出。
令人惊讶的是,这个和其他类似游戏让你感到惊讶的是它们内置了多少功能。例如,特别是在大灾变中,由于可用的数十个参数,特征和初始场景,你甚至无法创建一个没有谷歌某些指南的冲动的角色,更不用说整个游戏中发生的事件的多种变化。
由于它是一个开源代码的游戏,而且是一个用C ++编写的游戏,我们无法使用我们的静态代码分析器PVS-Studio进行检查,我正在积极参与其中。该项目的代码令人惊讶的高质量,但它仍然有一些小缺陷,其中一些我将在本文中讨论。
PVS-Studio已经检查了很多游戏。您可以在我们的文章“ 视频游戏开发中的静态分析:十大软件错误 ”中找到一些示例。
逻辑
例1:
此示例显示了经典的复制粘贴错误。
V501 “||”的左侧和右侧有相同的子表达式 operator:rng(2,7)<abs(z)|| rng(2,7)<abs(z)overmap.cpp 1503
bool overmap::generate_sub( const int z )
{
....
if( rng( 2, 7 ) < abs( z ) || rng( 2, 7 ) < abs( z ) )
{
....
}
....
}
检查相同的条件两次。程序员复制了表达式但忘记修改副本。我不确定这是否是一个严重的错误,但事实是检查不能正常工作。
另一个类似错误:
V501’&&‘运算符的左侧和右侧有相同的子表达式’one_in(100000 / to_turns (dur))’。player_hardcoded_effects.cpp 547
例2:
V728可以简化过度检查。’(A && B)|| (!A &&!B)'表达式等同于’bool(A)== bool(B)'表达式。inventory_ui.cpp 199
bool inventory_selector_preset::sort_compare( .... ) const
{
....
const bool left_fav = g->u.inv.assigned.count( lhs.location->invlet );
const bool right_fav = g->u.inv.assigned.count( rhs.location->invlet );
if( ( left_fav && right_fav ) || ( !left_fav && !right_fav ) ) {
return ....
}
....
}
这种情况在逻辑上是正确的,但它过于复杂。编写此代码的人应该对将要维护它的同事程序员表示同情。它可以用更简单的形式重写:if(left_fav == right_fav)。
另一个类似错误:
V728可以简化过度检查。’(A &&!B)|| (!A && B)'表达式等同于’bool(A)!= bool(B)'表达式。iuse_actor.cpp 2653
题外话题
我惊讶地发现今天以“roguelikes”为名的游戏只是roguelike游戏旧类型的温和代表。这一切都始于1980年的狂热游戏Rogue,它激发了许多学生和程序员用类似元素创建自己的游戏。我想很多影响力也来自桌面游戏DnD社区及其变化。