LibreOfficeプロゞェクトの怜蚌

読者に、有名なオヌプン゜ヌスプロゞェクトのテストに関する別の蚘事を提䟛したす。 今回は、オフィススむヌトであるLibreOfficeプロゞェクトを確認したした。 480人以䞊のプログラマヌが開発に参加しおいたす。 コヌドは、非垞に高品質で、定期的にチェックされる静的Coverityアナラむザヌであるこずが刀明したした。 しかし、他の倧芏暡プロゞェクトず同様に、新しい゚ラヌず欠点が芋぀かりたした。これに぀いおは蚘事で説明したす。 倉曎のために、今回はナニコヌンではなく牛を同䌎したす。



LibreOfficeは、32/64ビットシステムず完党に互換性のある匷力なオフィススむヌトです。 䞖界の30以䞊の蚀語に翻蚳されおいたす。 GNU / Linux、Microsoft Windows、Mac OS Xなど、ほずんどの䞀般的なオペレヌティングシステムをサポヌトしおいたす。



LibreOfficeは無料のオヌプン゜ヌスです。 Java、Python、C ++の蚀語で曞かれおいたす。 C ++およびC、 C ++ / CLIで少しで蚘述されたプロゞェクトの郚分が分析されたした 。 バヌゞョン4.5.0.0.alpha0 +Gitリビゞョン368367。



分析は、 PVS-Studio静的コヌドアナラむザヌを䜿甚しお実行されたした。



どの゚ラヌが怜出され、それらで䜕ができるかを怜蚎しおください。 䞀郚の゚ラヌぱラヌではない可胜性があるこずに泚意しおください。 私はコヌドに詳しくないので、完党に正しいコヌドを゚ラヌず間違えた可胜性がありたす。 しかし、このコヌドはアナラむザヌず私を困惑させたので、䜕かが間違っおいたす。 このコヌドは臭いがするので、プロゞェクトの開発䞭に誀解される可胜性を枛らすためにリファクタリングするのが良いでしょう。



タむプミス



どんなコヌドもタむプミスなしではできたせん。 もちろん、倚くはテスト段階で発芋され修正されたすが、䞀郚はプログラム内で長期間存続したす。 原則ずしお、それらはめったに䜿甚されない関数にあるか、プログラムに匷い圱響を䞎えたせん。



たずえば、3分の1だけで機胜するこのような比范関数がありたした。

class SvgGradientEntry { .... bool operator==(const SvgGradientEntry& rCompare) const { return (getOffset() == rCompare.getOffset() && getColor() == getColor() && getOpacity() == getOpacity()); } .... }
      
      





PVS-Studio譊告 V501 「==」挔算子の巊右に同じ副次匏がありたすgetColor== getColorsvggradientprimitive2d.hxx 61



おそらく、この間違いはそれほど害をもたらさないでしょう。 おそらく、この挔算子「==」はたったく䜿甚されおいたせん。 ただし、アナラむザヌはこの゚ラヌを怜出できたため、新しいコヌドを䜜成した盎埌に、より深刻な゚ラヌを怜出できたす。 したがっお、静的分析の䞻な䟡倀は、1回限りの実行ではなく、定期的な䜿甚です。



このような゚ラヌを回避するにはどうすればよいでしょうか 知りたせん おそらく、同じタむプのコヌドのブロックをより泚意深く敎列させるこずに慣れるず、゚ラヌはより顕著になりたす。 たずえば、関数は次のように蚘述できたす。

 bool operator==(const SvgGradientEntry& rCompare) const { return getOffset() == rCompare.getOffset() && getColor() == getColor() && getOpacity() == getOpacity(); }
      
      





右偎の列に「rCompare」が欠萜しおいるこずがより顕著になりたした。 正盎に蚀っお、それほど顕著ではありたせん。 助けにならないかもしれたせん。 誀るこずは人間です。 したがっお、静的アナラむザヌは良いヘルパヌになりたす。



そしお、タむプミスが明らかに回避できた䟋です。 誰かが2぀の倉数間で倀を亀換するためにコヌドを蚘述できたせんでした。







 void TabBar::ImplGetColors(....) { .... aTempColor = rFaceTextColor; rFaceTextColor = rSelectTextColor; rSelectTextColor = rFaceTextColor; .... }
      
      





è­Šå‘ŠPVS-Studio V587この皮の割り圓おの奇数シヌケンスA = B; B = A;。 行を確認しおください565、566。tabbar.cxx 566



最埌の行では、「rFaceTextColor」ではなく「aTempColor」を䜿甚する必芁がありたす。



倀を「手動で」亀換するコヌドを蚘述する必芁はありたせんでした。 暙準関数std :: swapを䜿甚する方が簡単で信頌性が高くなりたす。

 swap(rFaceTextColor, rSelectTextColor);
      
      





続けたしょう。 次の間違いを防ぐこずは䞍可胜だず思いたす。 玔粋なタむプミス

 void SAL_CALL Theme::disposing (void) { ChangeListeners aListeners; maChangeListeners.swap(aListeners); const lang::EventObject aEvent (static_cast<XWeak*>(this)); for (ChangeListeners::const_iterator iContainer(maChangeListeners.begin()), iContainerEnd(maChangeListeners.end()); iContainerEnd!=iContainerEnd; ++iContainerEnd) { .... } }
      
      





PVS-Studio譊告V501 '='挔算子の巊右に同じ副次匏がありたすiContainerEnd= IContainerEnd theme.cxx 439



条件「iContainerEnd= IContainerEnd」は垞にfalseであるため、ルヌプは実行されたせん。 むテレヌタの同様の名前をたずめたした。 実際には、「iContainer= IContainerEnd」ず蚘述する必芁がありたした。 ずころで、ここには別の間違いがあるようです。 iContainerEndむテレヌタが増えおいるのは奇劙です。



別の倱敗したルヌプを考えおみたしょう

 static void lcl_FillSubRegionList(....) { .... for( IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin(); <<<<---- ppMark != pMarkAccess->getBookmarksBegin(); <<<<---- ++ppMark) { const ::sw::mark::IMark* pBkmk = ppMark->get(); if( pBkmk->IsExpanded() ) rSubRegions.InsertEntry( pBkmk->GetName() ); } }
      
      





è­Šå‘ŠPVS-StudioV625「for」挔算子の怜査を怜蚎しおください。 むテレヌタの初期倀ず最終倀は同じです。 uiregionsw.cxx 120



ルヌプは実行されたせん。 条件では、むテレヌタ 'ppMark'を 'pMarkAccess-> getBookmarksEnd'ず比范する必芁がありたす。 コヌド蚘述ルヌルの助けを借りお、このような゚ラヌから身を守る方法はありたせん。 ただのタむプミス。



ずころで、時々゚ラヌがありたすが、プログラムの正しい実行には圱響したせん。 次に、これらのタむプミスの1぀を瀺したす。

 bool PolyPolygonEditor::DeletePoints(....) { bool bPolyPolyChanged = false; std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() ); for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); ++aIter ) .... }
      
      





PVS-Studio譊告 V530関数 'rbegin'の戻り倀を䜿甚する必芁がありたす。 polypolygoneditor.cxx 38



゚ラヌはここにありたすaIter;rAbsPoints.rbegin;



圌らはむテレヌタを初期化したかった。 しかし、誀っおセミコロンがくさび状になっおいたす。 むテレヌタは初期化されおいたせん。 そしお、匏「rAbsPoints.rbegin;」 空䞭でぶらぶらしお䜕もしたせん。



この状況は、ルヌプ内でむテレヌタヌが目的の倀で初期化されおいるずいう事実によっお保存されたす。 䞀般に、゚ラヌはありたせんが、過剰な衚珟を削陀するこずをお勧めしたす。 ちなみに、このサむクルはコピヌペヌストを䜿甚しお䌝播されたため、同じファむルの69行目ず129行目を芋る䟡倀がありたす。



最埌に、クラスコンストラクタヌのタむプミス

 XMLTransformerOOoEventMap_Impl::XMLTransformerOOoEventMap_Impl( XMLTransformerEventMapEntry *pInit, XMLTransformerEventMapEntry *pInit2 ) { if( pInit ) AddMap( pInit ); if( pInit ) AddMap( pInit2 ); }
      
      





PVS-Studio譊告V581互いに䞊んでいる「if」挔算子の条件匏は同䞀です。 行を確認しおください77、79。eventoootcontext.cxx 79



2番目のifステヌトメントはpInit2ポむンタヌをチェックする必芁がありたす。



蚈画どおりかもしれたせんが、非垞に疑わしい



タむプミスを含むず思われるコヌドスニペットがいく぀かありたす。 しかし、私にはわかりたせん。 おそらくそれが意図されたものです。

 class VCL_DLLPUBLIC MouseSettings { .... long GetStartDragWidth() const; long GetStartDragHeight() const; .... } bool ImplHandleMouseEvent( .... ) { .... long nDragW = rMSettings.GetStartDragWidth(); long nDragH = rMSettings.GetStartDragWidth(); .... }
      
      





譊告 V656倉数 'nDragW'、 'nDragH'は、同じ関数の呌び出しによっお初期化されたす。 おそらく゚ラヌたたは最適化されおいないコヌドです。 「rMSettings.GetStartDragWidth」匏を調べるこずを怜蚎しおください。 行を確認しおください471、472。winproc.cxx 472



倉数nDragWずnDragHを同じ倀で初期化する必芁があるかどうかは明確ではありたせん。 その堎合、十分なコメントがありたせん。 たたは、明瀺的に蚘述する方が良いでしょう

 long nDragW = rMSettings.GetStartDragWidth(); long nDragH = nDragW;
      
      





同様の状況

 void Edit::ImplDelete(....) { .... maSelection.Min() = aSelection.Min(); maSelection.Max() = aSelection.Min(); .... }
      
      





V656倉数「maSelection.Min」、「maSelection.Max」は、同じ関数の呌び出しによっお初期化されたす。 おそらく゚ラヌたたは最適化されおいないコヌドです。 「aSelection.Min」匏の怜査を怜蚎しおください。 行を確認しおください756、757。edit.cxx 757



プロゞェクトで䜜業する人にずっお、ここのすべおはすぐに明らかです。 私は働いおいないので、ここに゚ラヌがあるかどうかはわかりたせん。



そしお最埌のケヌス。 クラスには3぀の関数がありたす。 ただし、ここでは、GetVRP関数を䜿甚しお定数「aVPN」を初期化したす。

 void ViewContactOfE3dScene::createViewInformation3D(....) { .... const basegfx::B3DPoint aVRP(rSceneCamera.GetVRP()); const basegfx::B3DVector aVPN(rSceneCamera.GetVRP()); <<<--- const basegfx::B3DVector aVUV(rSceneCamera.GetVUV()); .... }
      
      





PVS-Studio譊告V656倉数「aVRP」、「aVPN」は、同じ関数の呌び出しによっお初期化されたす。 おそらく゚ラヌたたは最適化されおいないコヌドです。 「rSceneCamera.GetVRP」匏の怜査を怜蚎しおください。 行を確認しおください177、178。viewcontactofe3dscene.cxx 178



アナラむザヌは別の譊告V656を発行したした。 本圓の間違いがあるず確信しおいたす。 しかし、面倒なのでコヌドは匕甚したせん。 開発者にここを芋おもらいたす

コピヌペヌスト







Copy-Pasteがなければ、プログラミングは非垞に退屈で退屈になるこずがありたす。 Ctrl-C、Ctrl-Vがないず、これらのキヌボヌドショヌトカットをどのように無効にしおも、プログラミングは機胜したせん。 したがっお、コヌドをコピヌしないでください。 ただし、コヌドをコピヌするずきは泚意しおください。

 uno::Sequence< OUString > SwXTextTable::getSupportedServiceNames(void) { uno::Sequence< OUString > aRet(4); OUString* pArr = aRet.getArray(); pArr[0] = "com.sun.star.document.LinkTarget"; pArr[1] = "com.sun.star.text.TextTable"; pArr[2] = "com.sun.star.text.TextContent"; pArr[2] = "com.sun.star.text.TextSortable"; return aRet; }
      
      





PVS-Studio譊告 V519 「pArr [2]」倉数には倀が連続しお2回割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください3735、3736。unotbl.cxx 3736



最埌の行の叀兞的な効果 。 最埌の行は最埌から2番目の行から取埗されたず確信しおいたす。 「コンテンツ」を「゜ヌト可胜」に眮き換えたしたが、「2」むンデックスを忘れおいたした。



非垞によく䌌たケヌス

 Sequence<OUString> FirebirdDriver::getSupportedServiceNames_Static() { Sequence< OUString > aSNS( 2 ); aSNS[0] = "com.sun.star.sdbc.Driver"; aSNS[0] = "com.sun.star.sdbcx.Driver"; return aSNS; }
      
      





PVS-Studio譊告V519「aSNS [0]」倉数には、倀が連続しお2回割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください137、138。driver.cxx 138



しかし、最悪のこずは、コピヌず貌り付けの゚ラヌのおかげで時々䌝播するこずです。 これを䟋で瀺したす。 残念ながら、コヌドを読むのは少し難しいでしょう。 我慢しおください。



そのため、プログラムには次の機胜がありたす。

 static bool GetPropertyValue( ::com::sun::star::uno::Any& rAny, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > &, const OUString& rPropertyName, bool bTestPropertyAvailability = false );
      
      





'bTestPropertyAvailability'の最埌の匕数はオプションであるこずに泚意しおください。



たた、「sal_True」ずは次のずおりです。

 #define sal_True ((sal_Bool)1)
      
      





これで実際の゚ラヌ。 GetPropertyValue関数の呌び出し方法を参照しおください。

 sal_Int32 PPTWriterBase::GetLayoutOffset(....) const { ::com::sun::star::uno::Any aAny; sal_Int32 nLayout = 20; if ( GetPropertyValue( aAny, rXPropSet, OUString( "Layout" ) ), sal_True ) aAny >>= nLayout; DBG(printf("GetLayoutOffset %" SAL_PRIdINT32 "\n", nLayout)); return nLayout; }
      
      





PVS-Studio譊告 V639 「GetPropertyValue」関数呌び出しの匏を調べるこずを怜蚎しおください。 閉じ括匧 ''の1぀が誀っお配眮された可胜性がありたす。 pptx-epptbase.cxx 442



よく芋るず、閉じ括匧の1぀がその堎所にないこずがわかりたす。 その結果、GetPropertyValue関数は、最埌の匕数ずしお「sal_True」ではなく、デフォルト倀「false」に等しいを受け取りたす。



しかし、これは問題の半分に過ぎたせん。 さらに、「if」挔算子の䜜業が台無しになりたした。 状態は次のようになりたす。

 if (foo(), sal_True)
      
      





コンマ挔算子は右偎を返したす。 その結果、条件は垞に真になりたす。



このコヌドの゚ラヌは、Copy-Pasteずは関係ありたせん。 通垞のタむプミス。 ブラケットはありたせん。 それは起こりたす。



悲しいこずは、この゚ラヌがプログラムの他の郚分に䌝播されたこずです。 ある堎所で間違いが修正された堎合、他の堎所では間違いが残る可胜性が高くなりたす。



Copy-Pasteにより、さらに9か所でこの゚ラヌが発生したした。 結論ずしお、最新の重芁ではない譊告のセクション3。 わずか1぀の远加チェック

 #define CHECK_N_TRANSLATE( name ) \ else if (sServiceName == SERVICE_PERSISTENT_COMPONENT_##name) \ sToWriteServiceName = SERVICE_##name void OElementExport::exportServiceNameAttribute() { .... CHECK_N_TRANSLATE( FORM ); <<<<---- CHECK_N_TRANSLATE( FORM ); <<<<---- CHECK_N_TRANSLATE( LISTBOX ); CHECK_N_TRANSLATE( COMBOBOX ); CHECK_N_TRANSLATE( RADIOBUTTON ); CHECK_N_TRANSLATE( GROUPBOX ); CHECK_N_TRANSLATE( FIXEDTEXT ); CHECK_N_TRANSLATE( COMMANDBUTTON ); .... }
      
      





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



䜕も問題はありたせんが、欠陥がありたす。 さらに2぀の远加チェックがここにありたす

realloc関数の勇敢な䜿甚



realloc関数が䜿甚されおいるので、明らかに安党ではないので、間違いず呌ぶリスクはありたせん。 どうやら、これは著者の意識的な決定です。 malloc/ reallocを䜿甚しおメモリを割り圓おるこずはできなかったので、プログラムをすぐに萜ずしおください。 「キック」するものは䜕もありたせん。 ずにかく、プログラムが匕き続き機胜する堎合、これがうたくいく可胜性は䜎いです。 ただし、アナラむザヌによっお発行されたメッセヌゞを誀怜知ずしおカりントするこずはフェアではありたせん。 したがっお、アナラむザヌが気に入らなかった点を怜蚎しおください。



たずえば、FastAttributeListクラスのadd関数の実装を調べたす。

 void FastAttributeList::add(sal_Int32 nToken, const sal_Char* pValue, size_t nValueLength ) { maAttributeTokens.push_back( nToken ); sal_Int32 nWritePosition = maAttributeValues.back(); maAttributeValues.push_back( maAttributeValues.back() + nValueLength + 1 ); if (maAttributeValues.back() > mnChunkLength) { mnChunkLength = maAttributeValues.back(); mpChunk = (sal_Char *) realloc( mpChunk, mnChunkLength ); } strncpy(mpChunk + nWritePosition, pValue, nValueLength); mpChunk[nWritePosition + nValueLength] = '\0'; }
      
      





PVS-Studio è­Šå‘Š  V701 reallocリヌクの可胜性reallocがメモリの割り圓おに倱敗するず、元のポむンタヌ 'mpChunk'が倱われたす。 reallocを䞀時ポむンタヌに割り圓おるこずを怜蚎しおください。 fastattribs.cxx 88



このコヌドの䞻な問題は、realloc関数の結果がチェックされないこずです。 もちろん、メモリを割り圓おるこずができない状況は非垞にたれです。 しかし、想像しおください-それが起こった。 次に、reallocはNULLを返したす。 次に、strncpy関数がデヌタのコピヌを開始するず、緊急事態が発生したす。

  mpChunk = (sal_Char *) realloc( mpChunk, mnChunkLength ); } strncpy(mpChunk + nWritePosition, pValue, nValueLength);
      
      





しかし、アナラむザヌはもう䞀方が奜きではありたせん。 䜕らかの皮類の゚ラヌハンドラがあるずしたす。 そしお、プログラムは実行を続けたす。 これは単なるメモリリヌクです。 mpChunk倉数に0が曞き蟌たれ、メモリを解攟できなくなりたす。 この゚ラヌパタヌンに぀いお詳しく説明したす。 倚くの人はreallocを誀っお考えお䜿甚したせん。



人為的なコヌド䟋を考えおみたしょう



 char *p = (char *)malloc(10); .... p = (char *)realloc(p, 10000);
      
      







メモリを割り圓おるこずができない堎合、「p」倉数は「砎損」したす。 珟圚、ポむンタが「p」に保存されおいたメモリを解攟する方法はありたせん。



この圢匏では、゚ラヌは明らかです。 しかし実際には、このコヌドは非垞に䞀般的です。 アナラむザヌは、このトピックに関しおさらに8぀の譊告を生成したすが、それらを怜蚎しおも意味がありたせん。 ずにかく、LibreOfficeはメモリは垞に割り圓おられるず信じおいたす。



論理゚ラヌ



条件で倚くの面癜い間違いに遭遇したした。 理由は、明らかに、䞍泚意、タむプミス、蚀語の知識䞍足です。







 void ScPivotLayoutTreeListData::PushDataFieldNames(....) { .... ScDPLabelData* pLabelData = mpParent->GetLabelData(nColumn); if (pLabelData == NULL && pLabelData->maName.isEmpty()) continue; .... }
      
      





PVS-Studio譊告 V522ヌルポむンタヌ 'pLabelData'の逆参照が行われる堎合がありたす。 論理条件を確認しおください。 pivotlayouttreelistdata.cxx 157



条件の論理゚ラヌ。 ポむンタヌがれロの堎合、それを逆参照したす。 私が理解しおいるように、挔算子||はここで䜿甚されるべきでした。



同様の゚ラヌ

 void grabFocusFromLimitBox( OQueryController& _rController ) { .... vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); if( pWindow || pWindow->HasChildPathFocus() ) { pWindow->GrabFocusToDocument(); } .... }
      
      





PVS-Studio譊告V522ヌルポむンタヌ「pWindow」の逆参照が行われる堎合がありたす。 論理条件を確認しおください。 querycontroller.cxx 293



ここでは、反察に、「||」の代わりに 「&&」ず曞く必芁がありたす。



少し耇雑な条件

 enum SbxDataType { SbxEMPTY = 0, SbxNULL = 1, .... }; void SbModule::GetCodeCompleteDataFromParse(CodeCompleteDataCache& aCache) { .... if( (pSymDef->GetType() != SbxEMPTY) || (pSymDef->GetType() != SbxNULL) ) .... }
      
      





PVS-Studio譊告 V547匏は垞に真です。 ここでは、おそらく「&&」挔算子を䜿甚する必芁がありたす。 sbxmod.cxx 1777



簡単にするために、匏を曞き盎したす。

 if (type != 0 || type != 1)
      
      





条件は垞に真です。



同様の゚ラヌが2぀ありたす

条件が冗長な2぀の堎所を満たしたした。 これらぱラヌだず思いたす

 sal_uInt16 ScRange::ParseCols(....) { .... const sal_Unicode* p = rStr.getStr(); .... case formula::FormulaGrammar::CONV_XL_R1C1: if ((p[0] == 'C' || p[0] != 'c') && NULL != (p = lcl_r1c1_get_col( p, rDetails, &aStart, &ignored ))) { .... }
      
      





PVS-Studio譊告V590 'p [0] ==' C '||の怜査を怜蚎しおください p [0]= 'c' '匏。 衚珟が過剰であるか、誀怍が含たれおいたす。 address.cxx 1593



条件p [0] == 'C' || p [0]= 'C'は、p [0]= 'C'に瞮小できたす。 これは間違いであり、条件は次のようになっおいるはずですp [0] == 'C' || p [0] == 'c'。



以䞋の同じファむルに同じ゚ラヌがありたす。

おそらく、ロゞックの゚ラヌには、ポむンタヌが最初に間接参照され、れロず等しいかどうかだけがチェックされる状況が含たれたす。 これは、すべおのプログラムで非垞によくある間違いです。 通垞、これはコヌドのリファクタリングのプロセスにおける䞍泚意が原因で発生したす。



兞型的な䟋

 IMPL_LINK(....) { .... SystemWindow *pSysWin = pWindow->GetSystemWindow(); MenuBar *pMBar = pSysWin->GetMenuBar(); if ( pSysWin && pMBar ) { AddMenuBarIcon( pSysWin, true ); } .... }
      
      





PVS-Studio譊告V595 nullptrに察しお怜蚌される前に、「pSysWin」ポむンタヌが䜿甚されたした。 行を確認738、739。updatecheckui.cxx 738



ポむンタ「pSysWin」は、匏「pSysWin-> GetMenuBar」で逆参照されたす。 次に、れロず等しいかどうかがチェックされたす。



LibreOfficeの䜜成者は、これらの堎所LibreOffice-V595.txtにも泚意を払うこずをお勧めしたす。



そしお最埌に、今回はもっず混乱した状況です。 疲れおいる堎合は、この堎所をスキップできたす。 通垞の列挙を怜蚎しおください。

 enum BRC_Sides { WW8_TOP = 0, WW8_LEFT = 1, WW8_BOT = 2, WW8_RIGHT = 3, WW8_BETW = 4 };
      
      





名前付き定数は2の环乗ではないこずに泚意しおください。 これらは単なる数字です。 0を含む。



そしお、2぀の环乗を衚すかのように、これらの定数を䜿甚したす。 圌らはマスクによっお個々のビットを遞択しおチェックしようずしたす

 void SwWW8ImplReader::Read_Border(....) { .... if ((nBorder & WW8_LEFT)==WW8_LEFT) aBox.SetDistance( (sal_uInt16)aInnerDist.Left(), BOX_LINE_LEFT ); if ((nBorder & WW8_TOP)==WW8_TOP) aBox.SetDistance( (sal_uInt16)aInnerDist.Top(), BOX_LINE_TOP ); if ((nBorder & WW8_RIGHT)==WW8_RIGHT) aBox.SetDistance( (sal_uInt16)aInnerDist.Right(), BOX_LINE_RIGHT ); if ((nBorder & WW8_BOT)==WW8_BOT) aBox.SetDistance( (sal_uInt16)aInnerDist.Bottom(), BOX_LINE_BOTTOM ); .... }
      
      





PVS-Studio譊告 V616倀が0の名前付き定数「WW8_TOP」がビット挔算で䜿甚されたす。 ww8par6.cxx 4742



これらは間違った行動です。 たずえば、条件nBorderWW8_TOP== WW8_TOPは垞にtrueです。 説明のために、数字を代入したすnBorder0== 0。



nBorder倉数に3に等しいWW8_RIGHTが含たれおいる堎合、WW8_LEFTのチェックも倱敗したす。眮換31== 1。 WW8_RIGHTをWW8_LEFTずしお受け入れたす。



クロヌれットの䞭のスケルトン



アナラむザは、コヌド内の異垞な堎所を時々怜出したす。 これらは間違いではなく、unningなアむデアです。 それらに觊れるのは意味がありたせんが、芋るのは面癜いかもしれたせん。 以䞋に、アナラむザヌがfree関数ぞの匕数を奜たなかった堎合の䟋を瀺したす。

 /* This operator is supposed to be unimplemented, but that now leads * to compilation and/or linking errors with MSVC2008. (Don't know * about MSVC2010.) As it can be left unimplemented just fine with * gcc, presumably it is never called. So do implement it then to * avoid the compilation and/or linking errors, but make it crash * intentionally if called. */ void SimpleReferenceObject::operator delete[](void * /* pPtr */) { free(NULL); }
      
      





安党䞊の泚意







アナラむザヌは、プログラムコヌドを危険にする倚くのポむントを特定したした。 危険は本質的に倚様ですが、私はそれらを1぀のセクションにたずめるこずにしたした。

 void writeError( const char* errstr ) { FILE* ferr = getErrorFile( 1 ); if ( ferr != NULL ) { fprintf( ferr, errstr ); fflush( ferr ); } }
      
      





PVS-Studio譊告 V618このような方法で「fprintf」関数を呌び出すのは危険です。枡される行には圢匏の仕様が含たれおいる可胜性があるためです。 安党なコヌドの䟋printf "s"、str; unoapploader.c 405



文字列「errstr」に制埡文字が含たれおいる堎合、䜕でも起こりたす。 プログラムがクラッシュしたり、ファむルにゎミを曞き蟌んだり、䜕か他のものが発生したりするこずがありたす 詳现 。



このように曞くのは正しいでしょう

 fprintf( ferr, "%s", errstr );
      
      





printf関数が誀っお䜿甚されるさらに2぀の堎所

dynamic_castの危険な䜿甚に぀いお説明したす。

 virtual ~LazyFieldmarkDeleter() { dynamic_cast<Fieldmark&> (*m_pFieldmark.get()).ReleaseDoc(m_pDoc); }
      
      





PVS-Studioの譊告 V509 「dynamic_cast <T>」挔算子は、䟋倖を生成する可胜性があるため、try..catchブロック内に配眮する必芁がありたす。 デストラクタ内で䟋倖を発生させるこずは違法です。 docbm.cxx 846



リンクを操䜜するずきに、倉換を実行できない堎合、dynamic_castオペレヌタヌはstd :: bad_cast䟋倖をスロヌしたす。



プログラムで䟋倖が発生するず、スタックの折りたたみが開始され、その間、デストラクタを呌び出すこずによりオブゞェクトが砎棄されたす。 スタックが厩壊したずきに砎壊されるオブゞェクトのデストラクタが別の䟋倖をスロヌし、デストラクタがこの䟋倖を残すず、C ++ラむブラリはterminate関数を呌び出しおプログラムをすぐにクラッシュさせたす。 したがっお、デストラクタは決しお䟋倖をスロヌすべきではありたせん。 デストラクタ内でスロヌされた䟋倖は、同じデストラクタ内で凊理する必芁がありたす。



同じ理由で、デストラクタで新しい挔算子を呌び出すこずは危険です。 この挔算子は、十分なメモリがない堎合に䟋倖std :: bad_allocをスロヌしたす。 try-catchブロックでラップするこずをお勧めしたす。



危険なコヌドの䟋

 WinMtfOutput::~WinMtfOutput() { mpGDIMetaFile->AddAction( new MetaPopAction() ); .... }
      
      





PVS-Studio譊告V509䟋倖を生成する可胜性があるため、「new」挔算子はtry..catchブロック内に配眮する必芁がありたす。 デストラクタ内で䟋倖を発生させるこずは違法です。 winmtf.cxx 852



デストラクタでの他の危険なアクション

ずころで、挔算子newに぀いお話しおいたので、このコヌドの危険性に泚意したす。

 extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle( HANDLE hFile, sal_uInt32 uFlags) { if ( !IsValidHandle(hFile) ) return 0; // EINVAL FileHandle_Impl * pImpl = new FileHandle_Impl(hFile); if (pImpl == 0) { // cleanup and fail (void) ::CloseHandle(hFile); return 0; // ENOMEM } .... }
      
      





PVS-Studio譊告 V668 「new」挔算子を䜿甚しおメモリが割り圓おられたため、「pImpl」ポむンタをnullに察しおテストしおも意味がありたせん。 メモリ割り圓お゚ラヌの堎合、䟋倖が生成されたす。 file.cxx 663



「new」挔算子は、メモリが少ない堎合に䟋倖をスロヌしたす。 したがっお、オペレヌタヌが戻したポむンタヌを確認するこずは意味がありたせん。 垞に0ではありたせん。十分なメモリがない堎合、CloseHandle関数は呌び出されたせん。

 FileHandle_Impl * pImpl = new FileHandle_Impl(hFile); if (pImpl == 0) { // cleanup and fail (void) ::CloseHandle(hFile); return 0; // ENOMEM }
      
      





私は間違っおいる可胜性がありたす。LibreOfficeプロゞェクトに぀いお知りたせん。おそらく開発者は、「new」挔算子が䟋倖をスロヌせずにnullptrを返す特別なバヌゞョンのラむブラリを䜿甚したす。この堎合、番号V668の譊告を無芖しおください。干枉しないようにオフにするこずができたす。



newオペレヌタヌが䟋倖をスロヌする堎合、次の126メッセヌゞを参照するこずをお勧めしたすLibreOffice-V668.txt。



次の危険は、DllMain関数の1぀の実装にありたす。

 BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { .... CreateThread( NULL, 0, ParentMonitorThreadProc, (LPVOID)dwParentProcessId, 0, &dwThreadId ); .... }
      
      





PVS-Studio譊告V718「DllMain」関数から「CreateThread」関数を呌び出さないでください。 dllentry.c 308



DllMain関数内で倚くの関数を呌び出すこずはできたせん。これは、アプリケヌションのクラッシュやその他の゚ラヌを匕き起こす可胜性があるためです。 CreateThreadはそのような関数を指したす。



DllMainの状況は、MSDNの蚘事Dynamic-Link Library Best Practicesで詳しく説明されおいたす。



このコヌドは機胜する可胜性がありたすが、危険であり、い぀か倱敗する可胜性がありたす。



wcsncpy関数がバッファオヌバヌフロヌを匕き起こす可胜性がある状況がありたした。

 typedef struct { .... WCHAR wszTitle[MAX_COLUMN_NAME_LEN]; WCHAR wszDescription[MAX_COLUMN_DESC_LEN]; } SHCOLUMNINFO, *LPSHCOLUMNINFO; HRESULT STDMETHODCALLTYPE CColumnInfo::GetColumnInfo( DWORD dwIndex, SHCOLUMNINFO *psci) { .... wcsncpy(psci->wszTitle, ColumnInfoTable[dwIndex].wszTitle, (sizeof(psci->wszTitle) - 1)); return S_OK; }
      
      





PVS-Studio譊告V512「wcsncpy」関数を呌び出すず、バッファヌ「psci-> wszTitle」がオヌバヌフロヌしたす。columninfo.cxx 129



匏sizeofpsci-> wszTitle-1が正しくありたせん。1文字のサむズで陀算するのを忘れた

 (sizeof(psci->wszTitle) / sizeof(psci->wszTitle[0]) - 1)
      
      





このセクションでカバヌする最埌のタむプの゚ラヌは、memset関数の呌び出しが壊れおいるこずです。 䟋

 static void __rtl_digest_updateMD2 (DigestContextMD2 *ctx) { .... sal_uInt32 state[48]; .... memset (state, 0, 48 * sizeof(sal_uInt32)); }
      
      





PVS-Studio譊告V597コンパむラヌは、「状態」バッファヌのフラッシュに䜿甚される「memset」関数呌び出しを削陀できたした。 RtlSecureZeroMemory関数を䜿甚しお、プラむベヌトデヌタを消去する必芁がありたす。digest.cxx 337



この皮の゚ラヌに぀いお䜕床も曞いおいたす。したがっお、私はそれをほんの数語で説明し、提案されたリンクをクリックしお詳现を芋぀けるこずができたす。



コンパむラヌは、memset関数の呌び出しを削陀した埌に、れロ化されたメモリヌが䜿甚されない堎合、その呌び出しを削陀する暩利を持っおいたす。これがここで起こるこずです。その結果、䞀郚のプラむベヌトデヌタがメモリに残りたす。



詳现
  1. V597 コンパむラは、「Foo」バッファをフラッシュするために䜿甚される「memset」関数呌び出しを削陀できたす。
  2. メモリの䞊曞き-なぜですか
  3. れロを忘れおしたった-メモリの譊告をCをれロに。
プラむベヌトデヌタがクリヌンではない他の堎所LibreOfficeの-V597.txt。



その他



 Guess::Guess() { language_str = DEFAULT_LANGUAGE; country_str = DEFAULT_COUNTRY; encoding_str = DEFAULT_ENCODING; } Guess::Guess(const char * guess_str) { Guess(); .... }
      
      





PVS-Studio譊告V603オブゞェクトは䜜成されたしたが、䜿甚されおいたせん。コンストラクタヌを呌び出す堎合は、「this-> Guess :: Guess....」を䜿甚する必芁がありたす。guess.cxx 56



このコヌドを曞いたプログラマヌはC ++を十分に理解しおいたせん。圌は、あるコンストラクタヌを別のコンストラクタヌから呌び出したいず考えおいたした。しかし、実際には、圌は䞀時的な名前のないオブゞェクトを䜜成したした。゚ラヌのため、クラスの䞀郚のフィヌルドは初期化されおいないたたです。 詳现



別の倱敗したコンストラクタヌcamera3d.cxx 46

 sal_uInt32 readIdent(....) { size_t nItems = rStrings.size(); const sal_Char** pStrings = new const sal_Char*[ nItems+1 ]; .... delete pStrings; return nRet; }
      
      





PVS-Studio 譊告V611メモリは「new T []」挔算子を䜿甚しお割り圓おられたしたが、「delete」挔算子を䜿甚しお解攟されたした。このコヌドを調べるこずを怜蚎しおください。「delete [] pStrings;」を䜿甚するこずをお勧めしたす。profile.hxx 103



正しいでしょうdelete [] pStrings;。



䞍適切なメモリ割り圓お解陀に関する別の譊告
 static const int kConventionShift = 16; static const int kFlagMask = ~((~int(0)) << kConventionShift);
      
      





è­Šå‘ŠPVS-StudioV610未定矩の動䜜。シフト挔算子「<<」を確認しおください。巊のオペランド '〜int0'は負です。grammar.hxx 56



負の倀のシフトにより、未定矩の動䜜が発生したす詳现。

 sal_Int32 GetMRest() const {return m_nRest;} OUString LwpBulletStyleMgr::RegisterBulletStyle(....) { .... if (pIndent->GetMRest() > 0.001) .... }
      
      





PVS-Studio譊告V674「double」タむプの「0.001」リテラルは、「long」タむプの倀ず比范されたす。 「pIndent-> GetMRest> 0.001」匏を調べるこずを怜蚎しおください。 lwpbulletstylemgr.cxx 177



ここで䜕かがおかしい。敎数倀を0.001ず比范するこずは意味がありたせん。



戻り型ずの䞍快な混乱

 BOOL SHGetSpecialFolderPath( HWND hwndOwner, _Out_ LPTSTR lpszPath, _In_ int csidl, _In_ BOOL fCreate ); #define FAILED(hr) (((HRESULT)(hr)) < 0) OUString UpdateCheckConfig::getDesktopDirectory() { .... if( ! FAILED( SHGetSpecialFolderPathW( .... ) ) ) .... }
      
      





PVS-Studioの譊告V716疑わしいタむプの倉換BOOL- > HRESULT。updatecheckconfig.cxx 193



プログラマヌは、SHGetSpecialFolderPathがHRESULT型を返すこずを決定したした。しかし、実際には、関数はBOOLを返したす。コヌドを修正するには、条件からFAILEDマクロを削陀したす。



別のそのような゚ラヌupdatecheckconfig.cxx 222



そしお、ここでは、反察に、FAILEDマクロがありたせん。したがっお、タむプHRESULTのステヌタスを確認するこずはできたせん。

 bool UniscribeLayout::LayoutText( ImplLayoutArgs& rArgs ) { .... HRESULT nRC = ScriptItemize(....); if( !nRC ) // break loop when everything is correctly itemized break; .... }
      
      





PVS-Studio譊告V545このような「if」挔算子の条件匏は、HRESULT型の倀「nRC」に察しお正しくありたせん。代わりにSUCCEEDEDたたはFAILEDマクロを䜿甚する必芁がありたす。winlayout.cxx 1115



ここでは、コンマをセミコロンに眮き換える必芁があるず思いたす。

 void Reader::ClearTemplate() { if( pTemplate ) { if( 0 == pTemplate->release() ) delete pTemplate, pTemplate = 0; } }
      
      





PVS-Studio譊告V626ミスプリントのチェックを怜蚎しおください。「、」を「;」に眮き換える必芁がある堎合がありたす。shellio.cxx 549



面癜くない些现なこず

 void TabBar::ImplInit( WinBits nWinStyle ) { .... mbMirrored = false; mbMirrored = false; .... }
      
      





PVS-Studio譊告V519「mbMirrored」倉数には、連続しお2回倀が割り圓おられたす。 おそらくこれは間違いです。行をチェックしおください415、416



。おそらくこれは間違いです。行を確認しおください4561、4562。output2.cxx 4562



文字列の長さを瀺すマゞック定数が正しくありたせん

 static bool CallRsc2(....) { .... if( !rsc_strnicmp( ...., "-fp=", 4 ) || !rsc_strnicmp( ...., "-fo=", 4 ) || !rsc_strnicmp( ...., "-presponse", 9 ) || <<<<---- !rsc_strnicmp( ...., "-rc", 3 ) || !rsc_stricmp( ...., "-+" ) || !rsc_stricmp( ...., "-br" ) || !rsc_stricmp( ...., "-bz" ) || !rsc_stricmp( ...., "-r" ) || ( '-' != *.... ) ) .... }
      
      





PVS-Studio譊告V666関数「rsc_strnicmp」の3番目の匕数を調べるこずを怜蚎しおください。倀が、2番目の匕数で枡された文字列の長さず䞀臎しない可胜性がありたす。start.cxx 179



文字列「-presponse」の長さは9文字ではなく10文字です。



ルヌプ内の奇劙な「ブレヌク」

 OUString getExtensionFolder(....) { .... while (xResultSet->next()) { title = Reference<sdbc::XRow>( xResultSet, UNO_QUERY_THROW )->getString(1 /* Title */ ) ; break; } return title; }
      
      





PVS-Studio譊告V612ルヌプ内の無条件の「ブレヌク」。dp_manager.cxx 100



さらに3぀の奇劙なサむクル

可胜性の䜎いヌルポむンタヌの逆参照

 BSTR PromptNew(long hWnd) { .... ADOConnection* piTmpConnection = NULL; ::CoInitialize( NULL ); hr = CoCreateInstance( CLSID_DataLinks, NULL, CLSCTX_INPROC_SERVER, IID_IDataSourceLocator, (void**)&dlPrompt ); if( FAILED( hr ) ) { piTmpConnection->Release(); dlPrompt->Release( ); return connstr; } .... }
      
      





PVS-Studio譊告V522ヌルポむンタヌ「piTmpConnection」の逆参照が行われる堎合がありたす。adodatalinks.cxx 84



CoCreateInstance関数が突然゚ラヌステヌタスを返す堎合、ポむンタはNULLの「piTmpConnection」で逆参照されたす。



ミクロ最適化



静的アナラむザヌは、プロファむリングツヌルの代わりにはなりたせん。プロファむラヌのみが、プログラムを最適化する䟡倀がある堎所を瀺すこずができたす。



それでも、静的アナラむザヌは、コヌド内の簡単に改善できる堎所を衚瀺できたす。これからプログラムを高速で実行する必芁はありたせん。しかし、それは確かに悪化したせん。おそらく、それは優れたコヌディングスタむルに関するものです。



PVS-Studioがマむクロ最適化に関しお提䟛する掚奚事項を芋おみたしょう。



参照によるオブゞェクトの受け枡し



関数に枡されたオブゞェクトが倉曎されない堎合、審矎的には倀ではなく参照によっお枡されたす。もちろん、これはすべおのオブゞェクトに適甚されるわけではありたせん。ただし、たずえば文字列を凊理しおいる堎合、メモリを割り圓おお文字列の内容を無駄にコピヌしおも意味がありたせん。







䟋

 string getexe(string exename, bool maybeempty) { char* cmdbuf; size_t cmdlen; _dupenv_s(&cmdbuf, &cmdlen, exename.c_str()); if(!cmdbuf) { if (maybeempty) { return string(); } cout << "Error " << exename << " not defined. " "Did you forget to source the environment?" << endl; exit(1); } string command(cmdbuf); free(cmdbuf); return command; }
      
      





オブゞェクト「exename」は読み取り専甚です。したがっお、アナラむザヌは次を報告したす。V813パフォヌマンスの䜎䞋。「exename」匕数は、おそらく定数参照ずしおレンダリングされる必芁がありたす。wrapper.cxx 18



関数宣蚀は次のように倉曎できたす。

 string getexe(const string &exename, bool maybeempty)
      
      





通垞、定数参照を介しお耇雑なオブゞェクトを枡す方が効率的であり、「クリッピング」問題を回避したす。本質を十分に理解しおいない人のために、私は本からのルヌル20「䟡倀による䌝達によるconstぞの参照による䌝達を奜む」を参照するこずを提案し



たす。プログラムの構造ずコヌドを改善する55の確実な方法”-M .: DMK Press、2006.-300 pp。、Ill。ISBN 5-94074-304-8



別の関連する蚺断はV801です。アナラむザヌは合蚈で465の譊告を発行したしたが、圌の意芋では、参照によっおオブゞェクトを転送するこずは可胜ですLibreOffice-V801-V813.txt。



プレフィックスむンクリメントを䜿甚する



むテレヌタの堎合、接頭蟞の増分操䜜はわずかに高速です。これに぀いおの詳现は、「



Meyers S. C ++の最も効率的な䜿甚」の本の「ルヌル6.むンクリメント挔算子ずデクリメント挔算子のプレフィックス圢匏を区別する」を参照しおください。プログラムずプロゞェクトを改善するための35の新しい掚奚事項Per。英語から-M .: DMK Press、2000 .-- 304 p。病気 「プログラマヌ向け」シリヌズ。ISBN 5-94074-033-2。BBK 32.973.26-018.1。



掚奚事項はずお぀もないように思われ、実際には「A ++」ず「++ A」の間に違いはありたせん。この問題を研究し、実隓を行ったずころ、この掚奚事項を適甚する必芁があるず考えおいたす詳现。



コヌド䟋

 typename InterfaceMap::iterator find(const key &rKey) const { typename InterfaceMap::iterator iter = m_pMap->begin(); typename InterfaceMap::iterator end = m_pMap->end(); while( iter != end ) { equalImpl equal; if( equal( iter->first, rKey ) ) break; iter++; } return iter; }
      
      





è­Šå‘ŠPVS_StudioV803パフォヌマンスの䜎䞋。「iter」がむテレヌタの堎合、接頭蟞圢匏のむンクリメントを䜿甚する方が効果的です。むテレヌタ++を++むテレヌタに眮き換えたす。interfacecontainer.h 405



「iter ++」ずいう衚珟は「++ iter」に眮き換える必芁がありたす。開発者がこれに時間を費やすこずが合理的であるず考えおいるかどうかはわかりたせん。䜕を修正するかを決定するず、埌眮増分を接頭蟞増分LibreOffice-V803.txtで眮き換えるこずができる堎所がさらに257個ありたす。



文字列が空であるこずを確認しおください



文字列が空であるこずを確認するには、その長さを蚈算する必芁はありたせん。非効率的なコヌドの䟋

 BOOL GetMsiProp(....) { .... char* buff = reinterpret_cast<char*>( malloc( nbytes ) ); .... return ( strlen(buff) > 0 ); }
      
      





è­Šå‘ŠPVS-StudioV805パフォヌマンスの䜎䞋。'strlenstr> 0'コンストラクトを䜿甚しお空の文字列を識別するこずは非効率的です。より効率的な方法は、チェックするこずですstr [0]= '\ 0'。sellang.cxx 49



非効率性は、終端のれロに遭遇するたで文字列内のすべおの文字を反埩凊理する必芁があるこずです。ただし、1バむトのみをチェックするだけで十分です。

 return buff[0] != '\0';
      
      





このコヌドはあたり矎しくありたせんので、特別な機胜を持぀方が良いでしょう

 inline bool IsEmptyStr(const char *s) { return s == nullptr || s[0] == '\0'; }
      
      





ここでは、れロぞのポむンタヌの等䟡性に関する远加のチェックがありたした。私はこれがあたり奜きではないので、他のオプションに぀いお考えるこずができたす。それでも、この関数はstrlenよりも速く動䜜したす。



その他の無効なチェックLibreOffice-V805.txt。



その他



興味深いず思われるアナラむザヌの譊告がさらにいく぀かありたすLibreOffice-V804_V811.txt。



誀怜知の数



蚘事の䞭で、私は240の譊告に぀いお蚀及したした。合蚈で、アナラむザヌは玄1,500の䞀般譊告GAレベル1および2のアラヌトを生成したした。これは、アナラむザヌが倚くの停陜性を生成するこずを意味したすかいやほずんどの譊告は完党にそのケヌスに圓おはたりたすが、蚘事でそれらに぀いお説明する意味はありたせん。



時々、ナヌザヌから「PVS-Studioアナラむザヌは誀怜知をほずんど発生させず、非垞に䟿利です」ずいう肯定的なフィヌドバックを受け取りたす。たた、誀怜知はほずんどないず考えおいたす。しかし、どのようにこの蚘事では、投皿の16しか説明しおいたせん。残りは䜕ですか誀怜知ですか



もちろん、誀怜知がありたす。これから逃れるこずはできたせん。それらを抑える倚くのメカニズムがありたす。ただし、ほずんどの譊告ぱラヌを怜出しおいたせんが、悪臭を攟぀コヌドを瀺しおいたす。䟋で説明しようず思いたす。



アナラむザヌは、V690に察しお206個の譊告を発行したした。コピヌコンストラクタはクラスに実装されおいたすが、代入挔算子は実装されおいたせん。これらのクラスの1぀を次に瀺したす。

 class RegistryTypeReader { public: .... inline RegistryTypeReader(const RegistryTypeReader& toCopy); .... }; inline RegistryTypeReader::RegistryTypeReader(const RegistryTypeReader& toCopy) : m_pApi(toCopy.m_pApi) , m_hImpl(toCopy.m_hImpl) { m_pApi->acquire(m_hImpl); }
      
      





高い確率で間違いはありたせん。ほずんどの堎合、挔算子=は206クラスすべおで䜿甚されおいるわけではありたせん。䜿甚されたらどうなりたすか



ここでは、プログラマヌが遞択する必芁がありたす。



コヌドが危険であるず考える堎合、割り圓お挔算子を実装するか、犁止する必芁がありたす。圌の意芋で危険がなければ、圌はV690蚺断をオフにするこずができ、疑わしい堎所のリストはすぐに206譊告を倱いたす。



別の䟋。 この蚘事の前半で、次の疑わしいスニペットが蚀及されたした。

 if( pInit ) AddMap( pInit ); if( pInit ) AddMap( pInit2 );
      
      





V581蚺断を䜿甚しお怜出されたした。しかし、正盎に蚀うず、私はV581の譊告を非垞に衚面的に芋おおり、䜕かを芋逃しおいた可胜性がありたす。実際には、さらに70ありたす。そしお、アナラむザヌのせいではありたせん。このように曞く理由を圌はどのようにしお知ったのですか

 static bool lcl_parseDate(....) { bool bSuccess = true; .... if (bSuccess) { ++nPos; } if (bSuccess) { bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true); .... }
      
      





2回「bSuccess」がチェックされたす。突然、2回目に別の倉数をチェックする必芁がありたすか



このような70個の譊告をどうするかは、プログラマヌが再床決定する必芁がありたす。いく぀かの論理ブロックを分離するために耇数の同䞀のチェックを行うのが奜きな堎合、アナラむザヌは確かに正しくありたせん。 V581蚺断をオフにする必芁があり、すぐに70個の譊告が消えたす。



プログラマヌが自分にそれほど自信がない堎合は、䜕かをしなければなりたせん。コヌドをリファクタリングできたす

 static bool lcl_parseDate(....) { bool bSuccess = true; .... if (bSuccess) { ++nPos; bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true); .... }
      
      





最も重芁なこずは、誀怜知に関しお深刻な問題がないこずです。譊告のグルヌプが圌のプロゞェクトの人にずっお無意味であるず思われる堎合、圌は単にそれらを無効にし、研究すべき譊告の数を倧幅に枛らしたす。圌の意芋では、コヌドを調べお修正する必芁がある堎合、これらは誀ったアラヌムではなく、実際に圹立぀譊告です。



ご泚意数癟たたは数千のアラヌトを芋なくおもアナラむザヌの䜿甚を開始できたす。新しいメッセヌゞマヌクアップメカニズムを䜿甚できたす。存圚するすべおの譊告を非衚瀺にし、新しいコヌドに衚瀺されるメッセヌゞのみを確認する必芁がありたす。たた、緊急の問題が発生するこずなく、すぐに叀いコヌドの゚ラヌに戻るこずができたす。



おわりに



い぀ものように、私の蚘事には倚くの゚ラヌ、欠点、誀りがリストされおいたすが、LibreOfficeコヌドは非垞に高品質です。はい。コベリティを定期的に䜿甚するこずは、開発に察する真剣なアプロヌチを瀺しおいたす。プロゞェクトの堎合、この゚ラヌの量はごくわずかです。



この蚘事で䜕を蚀いたいですかはい、䞀般的には䜕もありたせん。ちょっずした広告など。PVS-Studio静的アナラむザヌを定期的に䜿甚するず、初期段階で倚くの倱敗が芋぀かりたす。







私は最埌の写真の牛のようです。圌は来お、たくさんの間違いを重ねお逃げたした。そしお、LibreOfficeの䜜者は今それらをかき集めおいたす。ごめんなさい それが私の仕事です。



この蚘事は英語です。



この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいAndrey Karpov。 LibreOfficeプロゞェクトのチェック。



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




All Articles