PVS-StudioがOpenMWをチェックします:Morrowindの世界ではすべてがスムーズに進んでいない







OpenMWプロジェクトをPVS-Studioでテストし、この小さな記事を書きました。 エラーが少なすぎました。 しかし、私はこのプロジェクトの検証に関する記事を書くように頼まれました。



Openmw



OpenMWは、オープンソースゲームのすべての機能の本格的な実装である、人気のあるRPG Morrowindを再現する試みです。 OpenMWを実行するには、元のMorrowindディスクが必要です。



ソースコードは、 https//code.google.com/p/openmw/から入手できます



疑わしい場所が見つかりました



フラグメントN1

std::string getUtf8(unsigned char c, ToUTF8::Utf8Encoder& encoder, ToUTF8::FromType encoding) { .... conv[0xa2] = 0xf3; conv[0xa3] = 0xbf; conv[0xa4] = 0x0; conv[0xe1] = 0x8c; conv[0xe1] = 0x8c; <<<<==== conv[0xe3] = 0x0; .... }
      
      





PVS-Studio警告:V519「conv [0xe1]」変数には値が連続して2回割り当てられます。 おそらくこれは間違いです。 行を確認:103、104。openmw fontloader.cpp 104



これはおそらくタイプミスです。 強調表示された行では、インデックス0xe2が使用される可能性が最も高くなります。



フラグメントN2

 enum Flags { .... NoDuration = 0x4, .... } bool CastSpell::cast (const ESM::Ingredient* ingredient) { .... if (!magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) .... }
      
      





PVS-Studio警告:V564「&」演算子はブール型の値に適用されます。 括弧を含めるのを忘れているか、「&&」演算子を使用することを意図している可能性があります。 openmw spellcasting.cpp 717



エラーは、操作の優先度に関連しています。 最初に、アクション(!MagicEffect-> mData.mFlags)が実行されます。 結果:0または1。その後、アクションが実行されます:0と4または1と4。これは実際的な意味を持ちません。 ほとんどの場合、コードは次のようになります。

 if ( ! (magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) )
      
      





フラグメントN3

 void Clothing::blank() { mData.mType = 0; mData.mWeight = 0; mData.mValue = 0; mData.mEnchant = 0; mParts.mParts.clear(); mName.clear(); mModel.clear(); mIcon.clear(); mIcon.clear(); mEnchant.clear(); mScript.clear(); }
      
      





PVS-Studio警告:V586同じリソースの割り当てを解除するために、「クリア」機能が2回呼び出されます。 行をチェックしてください:48、49。components loadclot.cpp 49



mIconオブジェクトは2回クリアされます。 2回目のクリーニングは不要であるか、何か他のクリーニングが必要でした。



フラグメントN4

 void Storage::loadDataFromStream( ContainerType& container, std::istream& stream) { std::string line; while (!stream.eof()) { std::getline( stream, line ); .... } .... }
      
      





警告PVS-Studio:V663無限ループが可能です。 「cin.eof()」条件は、ループから抜けるには不十分です。 「cin.fail()」関数呼び出しを条件式に追加することを検討してください。 コンポーネントtranslation.cpp 45



クラス 'std :: istream'を使用する場合、関数 'eof()'を呼び出してループを終了するだけでは不十分です。 データの読み取り中に障害が発生した場合、「eof()」関数を呼び出すと、常に値「false」が返されます。 この場合にループを完了するには、関数 'fail()'によって返された値の追加チェックが必要です。



フラグメントN5

 class Factory { .... bool getReadSourceCache() { return mReadSourceCache; } bool getWriteSourceCache() { return mReadSourceCache; } .... bool mReadSourceCache; bool mWriteSourceCache; .... };
      
      





PVS-Studio警告:V524「getWriteSourceCache」関数の本体が「getReadSourceCache」関数の本体と完全に同等であることは奇妙です。 コンポーネントfactory.hpp 209



getWriteSourceCache()関数は次のようになっているはずです。

 bool getWriteSourceCache() { return mWriteSourceCache; }
      
      





フラグメントN6、N7、N8

 std::string rangeTypeLabel(int idx) { const char* rangeTypeLabels [] = { "Self", "Touch", "Target" }; if (idx >= 0 && idx <= 3) return rangeTypeLabels[idx]; else return "Invalid"; }
      
      





PVS-Studio警告:V557アレイがオーバーランする可能性があります。 'idx'インデックスの値は3に達する可能性があります。esmtoollabels.cpp 502



配列インデックスのチェックが正しくありません。 変数 'idx'が3に等しい場合、配列を超えます。



正しく:

 if (idx >= 0 && idx < 3)
      
      





同様の状況がさらに2つの場所で発生しました。

フラグメントN9

 enum UpperBodyCharacterState { UpperCharState_Nothing, UpperCharState_EquipingWeap, UpperCharState_UnEquipingWeap, .... }; bool CharacterController::updateWeaponState() { .... if((weaptype != WeapType_None || UpperCharState_UnEquipingWeap) && animPlaying) .... }
      
      





PVS-Studio警告:V560条件式の一部であるUpperCharState_UnEquipingWeapは常に真です。 openmw character.cpp 949



この状態は非常に疑わしいです。 これで、「if(animPlaying)」に簡略化できます。 明らかに何かが間違っています。



フラグメントN10、N11

 void World::clear() { mLocalScripts.clear(); mPlayer->clear(); .... if (mPlayer) .... }
      
      





PVS-Studio警告:V595 nullptrに対して検証される前に、「mPlayer」ポインターが使用されました。 行を確認:234、245。openmw worldimp.cpp 234



同様:V595 nullptrに対して検証される前に、「mBody」ポインターが使用されました。 行を確認してください:95、99。openmw physic.cpp 95



フラグメントN12

 void ExprParser::replaceBinaryOperands() { .... if (t1==t2) mOperands.push_back (t1); else if (t1=='f' || t2=='f') mOperands.push_back ('f'); else std::logic_error ("failed to determine result operand type"); }
      
      





PVS-Studio警告:V596オブジェクトは作成されましたが、使用されていません。 「throw」キーワードが欠落している可能性があります:throw logic_error(FOO); コンポーネントexprparser.cpp 101



キーワード「throw」を忘れました。 コードは次のようになります。

 throw std::logic_error ("failed to determine result operand type");
      
      





おわりに



PVS-Studioの買収と開発プロセスでのこのツールの導入により、開発プロセスがスピードアップされ、エラーが早期に検出され、その結果、プロジェクトが改善されます。



この記事は英語です。



この記事を英語圏の聴衆と共有したい場合は、翻訳へのリンクを使用してください:Andrey Karpov。 PVS-StudioがOpenMWをチェック:Morrowind Universeですべてがうまくいくわけではありません



記事を読んで質問がありますか?
多くの場合、記事には同じ質問が寄せられます。 ここでそれらに対する回答を収集しました: PVS-StudioおよびCppCatバージョン2014に関する記事の読者からの質問への回答 。 リストをご覧ください。




All Articles