X-Ray゚ンゞンの異垞を探す

X-Ray Engineは、2014幎9月16日にSTALKERシリヌズのゲヌムで䜿甚されるゲヌム゚ンゞンです。その゜ヌスコヌドはパブリックドメむンで公開され、それ以来ファンが開発を続けおいたす。 プロゞェクトの倧芏暡さ、ゲヌムの膚倧な数のバグ-これらはすべお、PVS-Studio静的コヌドアナラむザヌの機胜の優れたデモを提䟛したす。









゚ントリヌ



X-Rayは、りクラむナのGSC GameWorldによっおゲヌムSTALKERShadow of Chernobyl甚に䜜成されたした。 この゚ンゞンには、DirectX 8.1 / 9.0c / 10 / 10.1 / 11、物理゚ンゞンずサりンド゚ンゞン、マルチプレむダヌ、A-Life人工知胜システムをサポヌトするレンダリングが含たれおいたす。 その埌、同瀟は新しいゲヌム甚にバヌゞョン2.0゚ンゞンを䜜成したしたが、開発は䞭止され、゜ヌスコヌドはネットワヌクに流れ蟌みたした。



プロゞェクトずそのすべおの䟝存関係は、Visual Studio 2015で簡単に組み立おられたす。確認のため、 GitHubのリポゞトリからの1.6゚ンゞンの゜ヌスコヌドず、 参照によりダりンロヌドできるPVS-Studio 6.04静的コヌドアナラむザヌを䜿甚したした。



コピヌペヌスト



たず、コヌドのコピヌに関連する゚ラヌを怜蚎しおください。 さたざたなケヌスでのそれらの発生のシナリオは通垞類䌌しおいたす圌らはコヌドをコピヌし、いく぀かの倉数を倉曎し、いく぀かを忘れたした。 このような゚ラヌはコヌドベヌス党䜓に急速に広がり、静的アナラむザヌがないず芋逃しやすくなりたす。







MxMatrix& MxQuadric::homogeneous(MxMatrix& H) const { .... unsigned int i, j; for(i=0; i<A.dim(); i++) for(j=0; j<A.dim(); i++) H(i,j) = A(i,j); .... }
      
      





PVS-Studioè­Šå‘Š  V533 「for」挔算子内で誀った倉数がむンクリメントされおいる可胜性がありたす。 「i」の怜蚎を怜蚎しおください。 mxqmetric.cpp 76



アナラむザヌは、ネストされたforルヌプ内で倉数iがむンクリメントされ、倉数jがチェックされ、無限ルヌプが発生するこずを怜出したした。 おそらく、それをコピヌするずき、圌らは単にそれを倉曎するのを忘れおいたした。

 void CBaseMonster::settings_read(CInifile const * ini, LPCSTR section, SMonsterSettings &data) { .... if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_base"), "%f,%f,%f", &data.m_attack_effector.ppi.color_base.r, &data.m_attack_effector.ppi.color_base.g, &data.m_attack_effector.ppi.color_base.b); if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_gray"), "%f,%f,%f", &data.m_attack_effector.ppi.color_gray.r, &data.m_attack_effector.ppi.color_gray.g, &data.m_attack_effector.ppi.color_gray.b); if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_add"), "%f,%f,%f", &data.m_attack_effector.ppi.color_add.r, &data.m_attack_effector.ppi.color_add.g, &data.m_attack_effector.ppi.color_add.b); .... }
      
      





PVS-Studioの譊告 

このフラグメントでは、いく぀かの同䞀の条件匏が連続しお䜿甚されおいたす。 明らかに、 ifブランチの本䜓のコヌドに埓っお、 color_baseをcolor_grayずcolor_addに眮き換える必芁がありたす。

 /* process a single statement */ static void ProcessStatement(char *buff, int len) { .... if (strncmp(buff,"\\pauthr\\",8) == 0) { ProcessPlayerAuth(buff, len); } else if (strncmp(buff,"\\getpidr\\",9) == 0) { ProcessGetPid(buff, len); } else if (strncmp(buff,"\\getpidr\\",9) == 0) { ProcessGetPid(buff, len); } else if (strncmp(buff,"\\getpdr\\",8) == 0) { ProcessGetData(buff, len); } else if (strncmp(buff,"\\setpdr\\",8) == 0) { ProcessSetData(buff, len); } }
      
      





PVS-Studio è­Šå‘Š  V517 「ifA{...} else ifA{...}」パタヌンの䜿甚が怜出されたした。 論理゚ラヌが存圚する可胜性がありたす。 行を確認しおください1502、1505。gstats.c 1502



前の䟋ず同様に、2぀の同䞀の条件がここで䜿甚されたす strncmpbuff、 "\\ getpidr \\"、9== 0 。 これが間違いであるか、単に到達䞍胜なコヌドであるかを確実に蚀うのは困難ですが、泚意を払う䟡倀があるこずは間違いありたせん。 getpdr / setpdrず同様に、 getpidr / setpidrを持぀ブロックが存圚する可胜性がありたす。

 class RGBAMipMappedCubeMap { .... size_t height() const { return cubeFaces[0].height(); } size_t width() const { return cubeFaces[0].height(); } .... };
      
      





PVS-Studioè­Šå‘Š  V524 「幅」機胜の本䜓が「高さ」機胜の本䜓ず完党に同等であるこずは奇劙です。 tpixel.h 1090



メ゜ッドheightずwidthは同じ本䜓を持ちたす。 立方䜓の面の寞法が蚈算されおいる堎合、ここで゚ラヌは発生しない可胜性がありたす。 ただし、次のようにwidthメ゜ッドを曞き換える方が適切です。

 size_t width() const { return cubeFaces[0].width(); }
      
      





C ++の誀甚



C ++は、プログラマに倚くの機䌚を䞎える玠晎らしい蚀語です...特に残酷な方法で自分自身を撃぀。 未定矩の動䜜、メモリリヌク、そしおもちろんタむプミス-このタむプの゚ラヌに぀いおは、珟圚のセクションで説明したす。







 template <class T> struct _matrix33 { public: typedef _matrix33<T>Self; typedef Self& SelfRef; .... IC SelfRef sMTxV(Tvector& R, float s1, const Tvector& V1) const { Rx = s1*(m[0][0] * V1.x + m[1][0] * V1.y + m[2][0] * V1.z); Ry = s1*(m[0][1] * V1.x + m[1][1] * V1.y + m[2][1] * V1.z); Rz = s1*(m[0][2] * V1.x + m[1][2] * V1.y + m[2][2] * V1.z); } .... }
      
      





PVS-Studioè­Šå‘Š  V591非void関数は倀を返す必芁がありたす。 _matrix33.h 435



メ゜ッドの最埌でreturn *これはスキップされたす。 暙準では、このようなコヌドは未定矩の動䜜に぀ながりたす。 戻り倀は参照であるため、戻り倀にアクセスしようずするず、プログラムがクラッシュする可胜性がありたす。

 ETOOLS_API int __stdcall ogg_enc(....) { .... FILE *in, *out = NULL; .... input_format *format; .... in = fopen(in_fn, "rb"); if(in == NULL) return 0; format = open_audio_file(in, &enc_opts); if(!format){ fclose(in); return 0; }; out = fopen(out_fn, "wb"); if(out == NULL){ fclose(out); return 0; } .... }
      
      





PVS-Studioè­Šå‘Š  V575 nullポむンタヌが「fclose」関数に枡されたす。 最初の匕数を調べたす。 ogg_enc.cpp 47



かなり興味深い䟋です。 アナラむザヌは、 fclose呌び出しの匕数がnullptrであるこずがわかりたした。これにより、関数呌び出しが無意味になりたす。 圌らはむンストリヌムを閉じたはずだず仮定できたす。

 void NVI_Image::ABGR8_To_ARGB8() { // swaps RGB for all pixels assert(IsDataValid()); assert(GetBytesPerPixel() == 4); UINT hxw = GetNumPixels(); for (UINT i = 0; i < hxw; i++) { DWORD col; GetPixel_ARGB8(&col, i); DWORD a = (col >> 24) && 0x000000FF; DWORD b = (col >> 16) && 0x000000FF; DWORD g = (col >> 8) && 0x000000FF; DWORD r = (col >> 0) && 0x000000FF; col = (a << 24) | (r << 16) | (g << 8) | b; SetPixel_ARGB8(i, col); } }
      
      





PVS-Studioの譊告

コヌドのこのセクションでは、論理挔算ずビット挔算が混同されおいたす。 結果はプログラマが期埅したものではありたせん。colは入力に関係なく垞に0x01010101です。



正しいオプション

 DWORD a = (col >> 24) & 0x000000FF; DWORD b = (col >> 16) & 0x000000FF; DWORD g = (col >> 8) & 0x000000FF; DWORD r = (col >> 0) & 0x000000FF;
      
      





別の奇劙なコヌド䟋

 VertexCache::VertexCache() { VertexCache(16); }
      
      





PVS-Studioè­Šå‘Š  V603オブゞェクトは䜜成されたしたが、䜿甚されおいたせん。 コンストラクタを呌び出す堎合は、「this-> VertexCache :: VertexCache....」を䜿甚する必芁がありたす。 vertexcache.cpp 6



むンスタンスを初期化するために別のコンストラクタヌを呌び出す代わりに、 VertexCache型の新しいオブゞェクトが䜜成され、すぐに砎棄されたす。 その結果、䜜成されたオブゞェクトのメンバヌは初期化されないたたになりたす。

 BOOL CActor::net_Spawn(CSE_Abstract* DC) { .... m_States.empty(); .... }
      
      





PVS-Studioè­Šå‘Š  V530関数 'empty'の戻り倀を䜿甚する必芁がありたす。 actor_network.cpp 657



アナラむザヌは、関数によっお返される倀が䜿甚されおいないこずを譊告したす。 プログラマヌはemptyメ゜ッドずclearメ゜ッドを混同しおいるようです emptyは配列をクリアしたせんが、空かどうかを確認したす。



このような゚ラヌはさたざたなプロゞェクトでよく芋られたす。 問題は、 空の名前が明らかではないこずです。䞀郚の人は、それをアクション-削陀ずしお認識しおいたす。 このようなあいたいさを避けるために、has、is動詞をメ゜ッドの先頭に远加するこずをお勧めしたす。実際、 isEmptyずclearは混同しにくいです。



同様の譊告



V530関数 'unique'の戻り倀を䜿甚する必芁がありたす。 uidragdroplistex.cpp 780

 size_t xrDebug::BuildStackTrace(EXCEPTION_POINTERS* exPtrs, char *buffer, size_t capacity, size_t lineCapacity) { memset(buffer, capacity*lineCapacity, 0); .... }
      
      





PVS-Studioè­Šå‘Š  V575 「memset」関数は「0」芁玠を凊理したす。 3番目の匕数を調べたす。 xrdebug.cpp 104



memsetが呌び出されたずき、匕数は混同され、その結果、バッファは元々意図されおいたようにリセットされたせん。 同様の゚ラヌは、怜出するのが非垞に難しいため、プロゞェクト内で非垞に長い間発生する可胜性がありたす。 そのような堎所では、静的アナラむザヌがプログラマヌの助けになりたす。



memsetの正しい䜿甚

 memset(buffer, 0, capacity*lineCapacity);
      
      





次の゚ラヌは、䞍正な圢匏の論理匏に関連しおいたす。

 void configs_dumper::dumper_thread(void* my_ptr) { .... DWORD wait_result = WaitForSingleObject( this_ptr->m_make_start_event, INFINITE); while ( wait_result != WAIT_ABANDONED) || (wait_result != WAIT_FAILED)) .... }
      
      





PVS-Studioè­Šå‘Š  V547匏は垞に真です。 ここでは、おそらく「&&」挔算子を䜿甚する必芁がありたす。 configs_dumper.cpp 262



'x= A ||ずいう圢匏の匏 x= b 'は垞に真です。 おそらく挔算子の代わりに|| 挔算子&&が暗黙指定されたした。



論理匏の゚ラヌの詳现に぀いおは、「 C / C ++の論理匏。専門家の誀解 」をご芧ください。

 void SBoneProtections::reload(const shared_str& bone_sect, IKinematics* kinematics) { .... CInifile::Sect &protections = pSettings->r_section(bone_sect); for (CInifile::SectCIt i=protections.Data.begin(); protections.Data.end() != i; ++i) { string256 buffer; BoneProtection BP; .... BP.BonePassBullet = (BOOL) ( atoi( _GetItem(i->second.c_str(), 2, buffer) )>0.5f); .... } }
      
      





PVS-Studioè­Šå‘Š  V674 「float」型の「0.5f」リテラルは、「int」型の倀ず比范されたす。 boneprotections.cpp 54



アナラむザヌは、敎数倀ず実定数の比范を芋぀けたした。 ここでは、類掚により、 atoiではなくatof関数を䜿甚する必芁がありたす。そうしないず、疑わしく芋えないようにこの比范を曞き換える䟡倀がありたす。 ただし、この䟋が間違いであるかどうかは間違いなく、曞いた開発者のみができたす。

 class IGameObject : public virtual IFactoryObject, public virtual ISpatial, public virtual ISheduled, public virtual IRenderable, public virtual ICollidable { public: .... virtual u16 ID() const = 0; .... } BOOL CBulletManager::test_callback( const collide::ray_defs& rd, IGameObject* object, LPVOID params) { bullet_test_callback_data* pData = (bullet_test_callback_data*)params; SBullet* bullet = pData->pBullet; if( (object->ID() == bullet->parent_id) && (bullet->fly_dist<parent_ignore_distance) && (!bullet->flags.ricochet_was)) return FALSE; BOOL bRes = TRUE; if (object){ .... } return bRes; }
      
      





PVS-Studioè­Šå‘Š  V595 nullptrに察しお怜蚌される前に、「オブゞェクト」ポむンタヌが䜿甚されたした。 行をチェックしおください42、47。level_bullet_manager_firetrace.cpp 42



オブゞェクト-> IDが逆参照された埌に、 nullptrの等䟡性に぀いおオブゞェクトポむンタヌをチェックしたす 。 オブゞェクトがnullptrの堎合、これはプログラムのクラッシュに぀ながりたす。

 #ifdef _EDITOR BOOL WINAPI DllEntryPoint(....) #else BOOL WINAPI DllMain(....) #endif { switch (ul_reason_for_call) { .... case DLL_THREAD_ATTACH: if (!strstr(GetCommandLine(), "-editor")) CoInitializeEx(NULL, COINIT_MULTITHREADED); timeBeginPeriod(1); break; .... } return TRUE; }
      
      





PVS-Studioè­Šå‘Š  V718 「CoInitializeEx」関数を「DllMain」関数から呌び出さないでください。 xrcore.cpp 205



CoInitializeExを含むWinAPI関数の䞀郚は、 DllMainの本䜓では䜿甚できたせん。 これは、 MSDNのドキュメントを読むこずで確認できたす。 この関数を曞き換える方法に぀いお明確なアドバむスをするこずはできたせんが、フロヌの盞互ブロックやクラッシュに぀ながる可胜性があるため、このような状況は危険であるこずを理解する必芁がありたす。



優先的な間違い



 int sgetI1( unsigned char **bp ) { int i; if ( flen == FLEN_ERROR ) return 0; i = **bp; if ( i > 127 ) i -= 256; flen += 1; *bp++; return i; }
      
      





PVS-Studioè­Šå‘Š  V532 「*ポむンタヌ++」パタヌンのステヌトメントの怜査を怜蚎しおください。 おそらく意味「*ポむンタヌ++」。 lwio.c 316



この゚ラヌは、むンクリメントの䜿甚が原因です。 わかりやすくするために、この匏を角かっこで曞き盎したす。

 *(bp++);
      
      





぀たり、コンテンツはアドレスbpにシフトされるのではなく、このコンテキストでは無意味なポむンタヌ自䜓にシフトされたす。 コヌドの䞋に* bp + = Nずいう圢匏のフラグメントがありたす。これが゚ラヌだず結論付けた理由です。



括匧を配眮するず、このような゚ラヌを回避でき、蚈算の順序がより明確になりたす。 たた、倉曎すべきでない匕数にconstを䜿甚するこずも良い方法です。



同様の譊告

 void CHitMemoryManager::load (IReader &packet) { .... if (!spawn_callback || !spawn_callback->m_object_callback) if(!g_dedicated_server) Level().client_spawn_manager().add( delayed_object.m_object_id,m_object->ID(),callback); #ifdef DEBUG else { if (spawn_callback && spawn_callback->m_object_callback) { VERIFY(spawn_callback->m_object_callback == callback); } } #endif // DEBUG }
      
      





PVS-Studioè­Šå‘Š  V563この「else」ブランチは、前の「if」ステヌトメントに適甚する必芁がある可胜性がありたす。 hit_memory_manager.cpp 368



このフラグメントでは、 elseブランチはその右結合性のために2番目のifを参照したすが 、これはコヌドのフォヌマットず䞀臎したせん。 幞いなこずに、このケヌスはプログラムの動䜜に圱響を䞎えたせんが、デバッグずテストのプロセスを耇雑にする可胜性がありたす。



掚奚事項は簡単です-倚少耇雑なブランチにブレヌスを配眮したす。

 void HUD_SOUND_ITEM::PlaySound(HUD_SOUND_ITEM& hud_snd, const Fvector& position, const IGameObject* parent, bool b_hud_mode, bool looped, u8 index) { .... hud_snd.m_activeSnd->snd.set_volume( hud_snd.m_activeSnd->volume * b_hud_mode?psHUDSoundVolume:1.0f); }
      
      





è­Šå‘ŠPVS-Studio  V502 「」挔算子は、予想ずは異なる方法で動䜜する可胜性がありたす。 「」挔算子は、「*」挔算子よりも優先順䜍が䜎くなりたす。 hudsound.cpp 108



䞉項条件挔算子は乗算よりも優先順䜍が䜎いため、挔算の順序は次のようになりたす。

 (hud_snd.m_activeSnd->volume * b_hud_mode)?psHUDSoundVolume:1.0f
      
      





明らかに、正しいコヌドは次のようになりたす。

 hud_snd.m_activeSnd->volume * (b_hud_mode?psHUDSoundVolume:1.0f)
      
      





䞉項挔算子、耇数のif-elseブランチ、たたはAND / OR挔算を含む匏は、䜙分なブラケットを配眮する方が適切な堎合です。



同様の譊告

远加の比范



 void CDestroyablePhysicsObject::OnChangeVisual() { if (m_pPhysicsShell){ if(m_pPhysicsShell)m_pPhysicsShell->Deactivate(); .... } .... }
      
      





PVS-Studioè­Šå‘Š  V571繰り返しチェック。 「ifm_pPhysicsShell」条件は、32行目ですでに怜蚌されおいたす。destroyablephysicsobject.cpp 33



この䟋では、 m_pPhysicsShellをダブルチェックしたす 。 ほずんどの堎合、2番目のチェックは䞍芁です。

 void CSE_ALifeItemPDA::STATE_Read(NET_Packet &tNetPacket, u16 size) { .... if (m_wVersion > 89) if ( (m_wVersion > 89)&&(m_wVersion < 98) ) { .... }else{ .... } }
      
      





PVS-Studioè­Šå‘Š  V571繰り返しチェック。 'm_wVersion> 89'条件は、987行目で既に怜蚌されおいたす。xrserver_objects_alife_items.cpp 989



非垞に奇劙なコヌド。 ifm_wVersion> 89の埌の匏がここで忘れられたか、䞀連のelse-ifのいずれかが忘れられたした。 この方法では、プロゞェクト開発者によるより詳现な怜蚎が必芁です。

 void ELogCallback(void *context, LPCSTR txt) { .... bool bDlg = ('#'==txt[0])||((0!=txt[1])&&('#'==txt[1])); if (bDlg){ int mt = ('!'==txt[0])||((0!=txt[1])&&('!'==txt[1]))?1:0; .... } }
      
      





PVS-Studioの譊告 

倉数bDlgおよびmtの初期化匏では、チェック0= Txt [1]は冗長です。 省略するず、匏が読みやすくなりたす。

 bool bDlg = ('#'==txt[0])||('#'==txt[1]); int mt = ('!'==txt[0])||('!'==txt[1])?1:0;
      
      





デヌタ型の゚ラヌ







 float CRenderTarget::im_noise_time; CRenderTarget::CRenderTarget() { .... param_blur = 0.f; param_gray = 0.f; param_noise = 0.f; param_duality_h = 0.f; param_duality_v = 0.f; param_noise_fps = 25.f; param_noise_scale = 1.f; im_noise_time = 1/100; im_noise_shift_w = 0; im_noise_shift_h = 0; .... }
      
      





PVS-Studioè­Šå‘Š  V636 ' 1/100 '匏は、暗黙的に 'int'型から 'float'型にキャストされたした。 分数郚分の損倱を避けるために、明瀺的な型キャストの䜿甚を怜蚎しおください。 䟋double A =doubleX/ Y;。 gl_rendertarget.cpp 245



敎数陀算挔算が実行されるため、1/100匏の倀は0です。 0.01fの倀を取埗するには、実際のリテラルを䜿甚しお匏を曞き換える必芁がありたす1 / 100.0f。 この動䜜は䜜成者によっお提䟛された可胜性がありたすが、゚ラヌはありたせん。

 CSpaceRestriction::merge(....) const { .... LPSTR S = xr_alloc<char>(acc_length); for ( ; I != E; ++I) temp = strconcat(sizeof(S),S,*temp,",",*(*I)->name()); .... }
      
      





PVS-Studioè­Šå‘Š  V579 strconcat関数は、ポむンタヌずそのサむズを匕数ずしお受け取りたす。 間違いかもしれたせん。 最初の匕数を調べたす。 space_restriction.cpp 201



strconcat関数は、最初のパラメヌタヌずしお、バッファヌの長さを取埗したす。 バッファヌSは LPSTRずしお、぀たり文字列ぞのポむンタヌずしお宣蚀されたす。 sizeofSは、バむト単䜍のポむンタヌのサむズ、぀たりsizeofchar *に等しくなり、文字列の文字数ではありたせん。 長さを蚈算するには、 strlenSを䜿甚したす。

 class XRCDB_API MODEL { .... u32 status; // 0=ready, 1=init, 2=building .... } void MODEL::build (Fvector* V, int Vcnt, TRI* T, int Tcnt, build_callback* bc, void* bcp) { .... BTHREAD_params P = { this, V, Vcnt, T, Tcnt, bc, bcp }; thread_spawn(build_thread,"CDB-construction",0,&P); while (S_INIT == status) Sleep(5); .... }
      
      





PVS-Studioè­Šå‘Š  V712コンパむラヌはこのサむクルを削陀するか、無限にする可胜性があるこずに泚意しおください。 これを回避するには、揮発性倉数たたは同期プリミティブを䜿甚したす。 xrcdb.cpp 100



ステヌタス倉数はルヌプ内で倉曎されないため、コンパむラヌは最適化ずしおS_INIT ==ステヌタスチェックを削陀できたす。 この動䜜を回避するには、 揮発性倉数たたはスレッド間のデヌタ同期の皮類を䜿甚する必芁がありたす。



同様の譊告

 void CAI_Rat::UpdateCL() { .... if (!Useful()) { inherited::UpdateCL (); Exec_Look (Device.fTimeDelta); CMonsterSquad *squad = monster_squad().get_squad(this); if (squad && ((squad->GetLeader() != this && !squad->GetLeader()->g_Alive()) || squad->get_index(this) == u32(-1))) squad->SetLeader(this); .... } .... }
      
      





PVS-Studio è­Šå‘Š  V547匏 'squad-> get_indexthis== u32-1'は垞にfalseです。 笊号なしchar型の倀の範囲[0、255]。 ai_rat.cpp 480



この匏が垞に停である理由を理解するために、個々のオペランドの倀を蚈算したす。 u32-1は0xFFFFFFFFたたは4294967295 です。squad-> get_index....メ゜ッドによっお返される型はu8であるため、その最倧倀は0xFFたたは255であり、厳密にu32-1未満です。 したがっお、このような比范の倀は垞にfalseになりたす 。 このコヌドは、デヌタ型をu8に倉曎するこずで簡単に修正できたす。

 squad->get_index(this) == u8(-1)
      
      





同じ蚺断が、笊号なし倉数の冗長比范に察しお機胜したす。

 namespace ALife { typedef u64 _TIME_ID; } ALife::_TIME_ID CScriptActionCondition::m_tLifeTime; IC bool CScriptEntityAction::CheckIfTimeOver() { return((m_tActionCondition.m_tLifeTime >= 0) && ((m_tActionCondition.m_tStartTime + m_tActionCondition.m_tLifeTime) < Device.dwTimeGlobal)); }
      
      





PVS-Studioの è­Šå‘Š  V547匏 'm_tActionCondition.m_tLifeTime> = 0'は垞にtrueです。 笊号なしの型の倀は垞に> 0です。script_entity_action_inline.h 115



m_tLifeTime倉数は笊号なしであるため、垞にれロ以䞊です。 これが䞍必芁なチェックであるか、ここに隠されたロゞックに゚ラヌがあるかどうか、開発者を刀断しおください。



同様の譊告



V547匏 'm_tActionCondition.m_tLifeTime <0'は垞にfalseです。 笊号なしの型の倀が<0になるこずはありたせんscript_entity_action_inline.h 143

 ObjectFactory::ServerObjectBaseClass * CObjectItemScript::server_object (LPCSTR section) const { ObjectFactory::ServerObjectBaseClass *object = nullptr; try { object = m_server_creator(section); } catch(std::exception e) { Msg("Exception [%s] raised while creating server object from " "section [%s]", e.what(),section); return (0); } .... }
      
      





è­Šå‘ŠPVS-Studio  V746タむプのスラむス。 䟋倖は、倀ではなく参照によっおキャッチする必芁がありたす。 object_item_script.cpp 39



std :: exception :: what関数は仮想であり、継承されたクラスでオヌバヌラむドできたす。 この䟋では、䟋倖は倀によっおキャッチされるため、クラスむンスタンスがコピヌされ、ポリモヌフィックタむプに関するすべおの情報が倱われたす。 この堎合のに目を向けるこずは無意味です。 䟋倖はリンクをキャッチするこずです

  catch(const std::exception& e) {
      
      





その他



 void compute_cover_value (....) { .... float value [8]; .... if (value[0] < .999f) { value[0] = value[0]; } .... }
      
      





PVS-Studioè­Šå‘Š  V570 「倀[0]」倉数はそれ自䜓に割り圓おられたす。 compiler_cover.cpp 260



倉数倀[0]はそれ自䜓に割り圓おられたす。 なぜこれが䞍明確なのか。 おそらく圌女は別の䟡倀を䞎えられおいたはずです。

 void CActor::g_SetSprintAnimation(u32 mstate_rl, MotionID &head, MotionID &torso, MotionID &legs) { SActorSprintState& sprint = m_anims->m_sprint; bool jump = (mstate_rl&mcFall) || (mstate_rl&mcLanding) || (mstate_rl&mcLanding) || (mstate_rl&mcLanding2) || (mstate_rl&mcJump); .... }
      
      





PVS-Studioè­Šå‘Š  V501 「||」の巊偎ず右偎に同䞀のサブ匏「mstate_rlmcLanding」がありたす 挔算子。 actoranimation.cpp 290



最も可胜性が高いのは、 mstate_rlずmcLandingの远加チェックだけですが、倚くの堎合、このような譊告はロゞックの゚ラヌず未怜蚌の列挙倀を通知したす。



同様の譊告

 RELATION_REGISTRY::RELATION_MAP_SPOTS::RELATION_MAP_SPOTS() { .... spot_names[ALife::eRelationTypeWorstEnemy] = "enemy_location"; spot_names[ALife::eRelationTypeWorstEnemy] = "enemy_location"; .... }
      
      





PVS-Studioè­Šå‘Š  V519倉数には倀が連続しお2回割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください57、58。relation_registry.cpp 58



アナラむザヌは、2぀の倀が行の1぀の倉数に割り圓おられおいるこずを怜出したした。 この堎合、それは単にデッドコヌドであり、削陀する必芁があるように芋えたす。

 void safe_verify(....) { .... printf("FATAL ERROR (%s): failed to verify data\n"); .... }
      
      





è­Šå‘ŠPVS-Studio  V576圢匏が正しくありたせん 。 「printf」関数の呌び出し䞭に、異なる数の実匕数が予期されたす。 予想2.珟圚1. entry_point.cpp 41



䞍十分な数の匕数がprintf関数に枡されたす。圢匏 's'は、文字列ぞのポむンタヌを枡す必芁があるこずを瀺したす。 このような状況は、メモリアクセス゚ラヌや緊急プログラムの終了に぀ながる可胜性がありたす。



おわりに







X-Ray゚ンゞンの゜ヌスコヌドを確認するず、倚数の䞍必芁なコヌドたたは疑わしいコヌドず、明らかに誀った危険な瞬間が明らかになりたした。 静的アナラむザヌは、開発の初期段階で゚ラヌを特定するのに圹立ち、プログラマヌの生掻を倧幅に簡玠化し、アプリケヌションの新しいバヌゞョンを䜜成する時間を解攟するこずに泚意しおください。





この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいPavel Belikov。 X-Ray Engineの異垞 。



蚘事を読んで質問がありたすか
倚くの堎合、蚘事には同じ質問が寄せられたす。 ここで回答を集めたした PVS-Studioバヌゞョン2015に関する蚘事の読者からの質問ぞの回答 。 リストをご芧ください。




All Articles