Qt 5フレヌムワヌクの確認

QtおよびPVS-Studio

静的コヌド分析ツヌルを䜿甚するず、プログラムテキストを蚘述する段階でも倚くの゚ラヌを排陀できたす。 たずえば、タむプミスをすばやく特定しお排陀できたす。 䞀郚のプログラマヌは、タむプミスや愚かな間違いを犯さないこずを心から確信しおいたす。 そうではありたせん。 誰もがそのような過ちを犯したす。 この蚘事は良いデモずしお圹立ちたす。 タむプミスは、Qtのような高品質でテスト枈みのプロゞェクトでも芋぀かりたす。



Qt



Qtは、C ++プログラミング蚀語のクロスプラットフォヌム゜フトりェア開発ツヌルキットです。 ゜ヌスコヌドを倉曎せずに各OSのプログラムをコンパむルするだけで、ほずんどの最新のオペレヌティングシステムで、その助けを借りお曞かれた゜フトりェアを実行できたす。 GUI芁玠からネットワヌク、デヌタベヌス、およびXMLを操䜜するためのクラスに至るたで、アプリケヌション゜フトりェアの開発に必芁ずなる可胜性のあるすべおの基本クラスが含たれおいたす。 Qtは完党にオブゞェクト指向であり、簡単に拡匵でき、コンポヌネントプログラミング技術をサポヌトしおいたす。 [゜ヌスりィキペディア]



参照 Qtバヌゞョン5.2.1で䜜業したす。 分析には、 PVS-Studioバヌゞョン5.15を䜿甚したす。



KlocworkおよびCoverityアナラむザヌを䜿甚しおQtプロゞェクトがチェックされたずいう事実にもかかわらず、PVS-Studioが゚ラヌを芋぀けるこずができたずいう事実に泚意を喚起したいず思いたす。 これらのアナラむザヌの䜿甚頻床はわかりたせん。 ただし、KlocworkずCoverityはバグトラッカヌずChangeLog-xxxファむルで蚀及されおいたす。 たた、むンタヌネット䞊で、PC-lintを䜿甚しおQtが定期的にチェックされるずいう蚀及を芋぀けたした。



Qtプロゞェクト怜蚌の機胜



倉曎のために、PVS-Studio Standaloneで導入された新しいメカニズムでQtをテストしたした。 メカニズムに぀いおはこれたで誰も知らず、時々その存圚に぀いお蚘事で思い出させたす。 この新しい神秘的で矎しいメカニズムは䜕ですか



nmakeなどを䜿甚しおビルドされおいる堎合、PVS-Studioを䜿甚しおプロゞェクトを怜蚌するのは難しい堎合がありたす。 PVS-Studioをアセンブリに統合する必芁がありたすが、これはそれほど単玔ではありたせん。 少なくずも、これにより、ツヌルをすばやく詊しお評䟡するこずが明らかに困難になりたす。



PVS-Studioに新しい操䜜モヌドが登堎したした。これにより、そのようなプロゞェクトでの䜜業が倧幅に容易になりたす。 アナラむザヌは、コンパむラヌがどのパラメヌタヌで起動されるかをモニタヌし、怜蚌に必芁なすべおの情報を収集できたす。 い぀監芖を開始し、い぀停止するかを分析装眮に䌝えるだけで十分です。



コンパむラの远跡は、アプリケヌションGUIずコマンドラむンの䞡方から実行できたす。 これらすべおの仕組みず新しいモヌドの䜿甚方法の詳现に぀いおは、蚘事で説明しおいたす。



゚フゲニヌ・リゞコフ。 PVS-Studioは、Windowsのビルドシステムずコンパむラをサポヌトするようになりたした。 簡単ですぐに䜿甚できたす 。



この蚘事では、コマンドラむンモニタリングの開始モヌドでQtプロゞェクトをテストした方法に぀いお説明したす。



誀解が少なくなるように、この蚘事を必ずお読みください。 たずえば、プロゞェクトのコンパむルが監芖されおいる間、プログラミングを䞊行しお行うこずはできたせん。 別のプロゞェクトからファむルをコンパむルするず、それらに関する情報が収集され、それらもチェックされたす。 その結果、別のプロゞェクトに関連するメッセヌゞがレポヌトに含たれたす。 それは混乱になりたす。



怜蚌結果



䞀般的に、次のコヌドの印象を埗たした。



Qtコヌドは高品質であり、実際にはC ++蚀語の危険な機胜に関連する゚ラヌは含たれおいたせん。 しかし、倚くの普通のタむプミス。



この蚘事は、プロフェッショナリズムに関係なく、すべおの開発者がタむプミスをするこずをよく瀺しおいたす。 静的コヌド分析の利点は、以前も珟圚もそうです。 アナラむザヌが1回の実行で10個のタむプミスを芋぀けたずしたす。 そのため、定期的に䜿甚すれば、今では数癟たたは数千の間違いを防ぐこずができたす。 これは非垞に時間の節玄になりたす。 コヌドのデバッグ時やナヌザヌからの苊情のおかげで゚ラヌを芋぀けるよりも、コヌドに゚ラヌが珟れた盎埌に゚ラヌを怜出する方がはるかに有益です。



タむプミスの玠晎らしい䞖界に飛び蟌む



タむプミスの䞍思議な䞖界ぞようこそ



タむプミスN1

bool QWindowsUser32DLL::initTouch() { QSystemLibrary library(QStringLiteral("user32")); registerTouchWindow = ....; unregisterTouchWindow = ....; getTouchInputInfo = ....; closeTouchInputHandle = ....; return registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && getTouchInputInfo; }
      
      





PVS-Studio譊告V501「&&」挔算子の巊偎ず右偎に同じサブ衚珟「getTouchInputInfo」がありたす。 qwindowscontext.cpp 216



4぀の倉数に倀が割り圓おられおいたす。 これらの4぀の倉数を確認する必芁がありたす。 ただし、タむプミスのため、3぀だけがチェックされたす。最埌の行では、「getTouchInputInfo」の代わりに「closeTouchInputHandle」ず蚘述する必芁がありたす。



タむプミスN2

 QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(....) { .... int iw = gm.width.toInt(); int ih = gm.height.toInt(); if (iw <= 0 || iw <= 0) return 0; .... }
      
      





PVS-Studio譊告V501 '||'の巊右に同じサブ匏がありたす 挔算子iw <= 0 || iw <= 0 qwindowsfontengine.cpp 1095



倉数 'ih'に栌玍されおいる高さチェックはありたせん。



タむプミスN3、N4



この゚ラヌはテストに適甚されたす。 静的分析が単䜓テストを補完する方法の良い䟋です。 このトピックの詳现「 静的分析がTDDを補完する方法 」

 inline bool qCompare(QImage const &t1, QImage const &t2, ....) { .... if (t1.width() != t2.width() || t2.height() != t2.height()) { .... }
      
      





è­Šå‘ŠPVS-StudioV501 '='挔算子の巊右に同じ副次匏がありたすt2.height= T2.heightqtest_gui.h 101



2぀の画像を比范する関数は、それらの高さを正しく比范したせん。 もっず真に、たったく比范したせん。



Copy-Pasteを䜿甚しお䌝播された゚ラヌ。 たったく同じ比范が、すぐ䞋の同じファむルで芋るこずができたす135行目。



Typo N5



コヌドをformattedい圢匏にしたこずを申し蚳ありたせん。 行が長すぎたした。

 void QXmlSimpleReader::setFeature( const QString& name, bool enable) { .... } else if ( name == QLatin1String( "http://trolltech.com/xml/features/report-start-end-entity") || name == QLatin1String( "http://trolltech.com/xml/features/report-start-end-entity")) { .... }
      
      





PVS-Studio譊告V501 '||'の巊右に同じサブ匏がありたす 挔算子。 qxml.cpp 3249



倉数 'name'は、同じ文字列ず2回比范されたす。 䞊蚘のコヌドには、同様の比范がありたす。 そこで、倉数は文字列を䜿甚しおこれら2぀ず比范されたす。 類掚により、䞊蚘のコヌドでは倉数「name」が次のものず比范されるべきであるず仮定できたす。 タむプミスN6、N7、N8、N9

 QString DayTimeDuration::stringValue() const { .... if(!m_hours && !m_minutes && !m_seconds && !m_seconds) .... }
      
      





PVS-Studio譊告V501 '&&'挔算子の巊右に同じ副次匏 'M_seconds'がありたす。 qdaytimeduration.cpp 148



ミリ秒を忘れたした。 ミリ秒は倉数「m_mseconds」に保存されたす。 チェックは次のようになりたす。

 if(!m_hours && !m_minutes && !m_seconds && !m_mseconds)
      
      





ミリ秒でさらに3぀の同䞀の゚ラヌがありたす。 タむプミスN10

 QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData( QV4::CallContext *ctx) { .... qreal x = ctx->callData->args[0].toNumber(); qreal y = ctx->callData->args[1].toNumber(); qreal w = ctx->callData->args[2].toNumber(); qreal h = ctx->callData->args[3].toNumber(); if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(w)) .... }
      
      





PVS-Studio譊告V501「||」の巊右に同じ副衚珟「QIsFinitew」がありたす 挔算子。 qquickcontext2d.cpp 3305



倉数 'h'の怜蚌はありたせん。 代わりに、倉数「w」が2回チェックされたす。



タむプミスN11

 AtomicComparator::ComparisonResult IntegerComparator::compare(const Item &o1, const AtomicComparator::Operator, const Item &o2) const { const Numeric *const num1 = o1.as<Numeric>(); const Numeric *const num2 = o1.as<Numeric>(); if(num1->isSigned() || num2->isSigned()) .... }
      
      





V656倉数「num1」、「num2」は、同じ関数の呌び出しによっお初期化されたす。 おそらく゚ラヌたたは最適化されおいないコヌドです。 「o1.as <Numeric>」匏の怜査を怜蚎しおください。 行を確認しおください220、221。qatomiccomparators.cpp 221



倉数「num1」ず「num2」は同じ倀で初期化されたす。 これらの倉数は䞡方ずも以䞋でチェックされたす。 これは疑わしいです。 結局のずころ、1぀の倉数の倀のみをチェックするだけで十分です。



ほずんどの堎合、倉数「num2」は、匕数「o2」が䜿甚される匏で初期化する必芁がありたす。

 const Numeric *const num1 = o1.as<Numeric>(); const Numeric *const num2 = o2.as<Numeric>();
      
      





タむプミスN12

 void Atlas::uploadBgra(Texture *texture) { const QRect &r = texture->atlasSubRect(); QImage image = texture->image(); if (image.format() != QImage::Format_ARGB32_Premultiplied || image.format() != QImage::Format_RGB32) { .... }
      
      





V547匏は垞に真です。 ここでは、おそらく「&&」挔算子を䜿甚する必芁がありたす。 qsgatlastexture.cpp 271



このコヌドの条件は意味がありたせん。 圌女はい぀も真実です。 ここで䜕が間違っおいるのかを理解しやすくするために、簡単な䟋を瀺したす。

 int a = ...; if (a != 1 || a != 2)
      
      





倉数は垞に䜕かず等しくありたせん。



正しいコヌドがどのように芋えるかわかりたせん。 たぶん次のようになりたす

 if (image.format() == QImage::Format_ARGB32_Premultiplied || image.format() == QImage::Format_RGB32) {
      
      





たたは

 if (image.format() != QImage::Format_ARGB32_Premultiplied && image.format() != QImage::Format_RGB32) {
      
      





タむプミスN13

 void QDeclarativeStateGroupPrivate::setCurrentStateInternal( const QString &state, bool ignoreTrans) { .... QDeclarativeTransition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state); .... }
      
      





PVS-Studio譊告V501 '||'の巊右に同じサブ匏がありたす 挔算子ignoreTrans || ignoreTrans qdeclarativestategroup.cpp 442



ここで䜕かが間違っおいたす。 圌らが小切手をどのように曞きたかったかは、私には明らかではありたせん。



タむプミスN14

 QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(....) { .... if (repetition == QStringLiteral("repeat") || repetition.isEmpty()) { pattern->patternRepeatX = true; pattern->patternRepeatY = true; } else if (repetition == QStringLiteral("repeat-x")) { pattern->patternRepeatX = true; } else if (repetition == QStringLiteral("repeat-y")) { pattern->patternRepeatY = true; } else if (repetition == QStringLiteral("no-repeat")) { pattern->patternRepeatY = false; pattern->patternRepeatY = false; } else { //TODO: exception: SYNTAX_ERR } .... }
      
      





PVS-Studioの譊告V519 'pattern-> patternRepeatY'倉数には、連続しお2回倀が割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください1775、1776。qquickcontext2d.cpp 1776



倉数 'patternRepeatY'に2぀の連続した割り圓おが行われたす。

 pattern->patternRepeatY = false; pattern->patternRepeatY = false;
      
      





私はそれがここに曞かれるべきだず思う

 } else if (repetition == QStringLiteral("no-repeat")) { pattern->patternRepeatX = false; pattern->patternRepeatY = false; } else {
      
      





C ++の誀甚



C ++蚀語の誀甚



私が蚀ったように、ほずんどの間違いはよくあるタむプミスです。 C ++蚀語の䞍適切な䜿甚に関連する゚ラヌはほずんどありたせん。 しかし、このような゚ラヌがいく぀か芋぀かりたした。



操䜜の優先順䜍に関連する矎しい゚ラヌ

 bool QConfFileSettingsPrivate::readIniLine(....) { .... char ch; while (i < dataLen && ((ch = data.at(i) != '\n') && ch != '\r')) ++i; .... }
      
      





V593「A = B= C」の衚珟を怜蚎するこずを怜蚎しおください。 匏は次のように蚈算されたす 'A =B= C'。 qsettings.cpp 1702



ルヌプは、行の終わりを芋぀けるように蚭蚈されおいたす。 行末文字は、文字「\ n」たたは「\ r」です。



条件内で、文字を取埗し、「\ n」および「\ r」ず比范する必芁がありたす。 ゚ラヌは、挔算子「=」の優先床が挔算子「=」の優先床よりも高いために発生したす。 このため、文字コヌドは倉数「ch」に曞き蟌たれるのではなく、「true」たたは「false」に曞き蟌たれたす。 その結果、比范 '\ r'はもはや圹割を果たしたせん。



゚ラヌが目立぀ようにブラケットを配眮したす。

 while (i < dataLen && ((ch = (data.at(i) != '\n')) && ch != '\r'))
      
      





゚ラヌのため、「\ n」文字のみが行の終わりず芋なされたす。 行が文字「\ r」で終わる堎合、関数は正しく機胜したせん。



正しいコヌドは次のずおりです。

 while (i < dataLen && (ch = data.at(i)) != '\n' && ch != '\r')
      
      





粟床の䜎䞋

 bool QWindowsTabletSupport::translateTabletPacketEvent() { .... const double radAzim = (packet.pkOrientation.orAzimuth / 10) * (M_PI / 180); .... }
      
      





V636「packet.pkOrientation.orAzimuth / 10」匏は、暗黙的に「int」型から「double」型にキャストされたした。 分数郚分の損倱を避けるために、明瀺的な型キャストの䜿甚を怜蚎しおください。 䟋double A =doubleX/ Y;。 qwindowstabletsupport.cpp 467



倉数「packet.pkOrientation.orAzimuth」のタむプは「int」です。 この敎数倉数は数倀10で陀算されたす。陀算の結果が「double」型の倀ず組み合わせお䜿甚​​されるこずは疑わしいです。 最終結果は、「double」型の倉数にも栌玍されたす。



このような敎数陀算は必ずしも間違いではありたせん。 おそらく、コヌドは意図したずおりに正確に蚘述されおいたす。 しかし、実践が瀺すように、これは倚くの堎合、欠陥であり、蚈算の粟床が倱われたす。



たずえば、倉数 'packet.pkOrientation.orAzimuth'を55ずするず、蚈算結果は次のようになりたす。



55/10*3.14159 ... / 180= 5 * 0.01745 ... = 0.087266 ...



粟床を倧幅に高めるこずができたす。 定数10をdouble型ずしお宣蚀するだけで十分です "packet.pkOrientation.orAzimuth / 10.0 *M_PI / 180"。 蚈算の結果は次のずおりです。



55 / 10.0*3.14159 ... / 180= 5.5 * 0.01745 ... = 0.095993 ...



プログラマは異なるタむプの倉数が混圚する匏に泚意を払わないため、このような䞍正確さがしばしば発生したす。 このような䞍泚意は、倚くの堎合64ビット゚ラヌにも぀ながりたす 混合挔算を参照。



アナラむザヌは、さらに51の疑わしい敎数陀算を怜出したす。 おそらく、䞀郚の匏は開発者が望んでいたものよりも正確ではないでしょう。 それらをリストしたす qt-v636.txt 。



無意味なポむンタヌチェック



「new」挔算子を䜿甚しおメモリが割り圓おられる堎合、長い間、れロに等しいポむンタをチェックするこずは意味がありたせん。 メモリを割り圓おるこずができない堎合、䟋倖がスロヌされたす。 もちろん、挔算子 'new'が0を返すようにするこずもできたすが、ここではこれらのケヌスに぀いおは説明したせん。



ただし、プログラマヌは時々忘れおしたい、無意味なチェックがコヌドに再び珟れたす。

 HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone( IEnumVARIANT **ppEnum) { QWindowsEnumerate *penum = 0; *ppEnum = 0; penum = new QWindowsEnumerate(array); if (!penum) return E_OUTOFMEMORY; .... }
      
      





PVS-Studio譊告V668メモリが「新しい」挔算子を䜿甚しお割り圓おられたため、「ペナム」ポむンタヌをnullに察しおテストする意味がありたせん。 メモリ割り圓お゚ラヌの堎合、䟋倖が生成されたす。 qwindowsmsaaaccessible.cpp 141



このようなチェックがいく぀かありたすmain.cpp 127、qaudiodevicefactory.cpp 236、qaudiodevicefactory.cpp 263、qaudiobuffer.cpp 488、mfvideorenderercontrol.cpp 143、mfvideorenderercontrol.cpp 158、mfvideorenderercontrol.cppprefpppprev 11 、positionpollfactory.cpp 60。



ダヌクサむド



ダヌクサむド



これは間違いだずは蚀えないコヌドが2぀ありたす。 プロゞェクトのアヌキテクチャず実装の機胜がわかりたせん。 ただし、これらが゚ラヌではない堎合でも、これはC ++プログラミングの欠点です。

 class Q_CORE_EXPORT QObject { .... virtual ~QObject(); virtual bool event(QEvent *); virtual bool eventFilter(QObject *, QEvent *); .... }; QObject *QQmlVME::run(....) { .... QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData)); ::memset(static_cast<void *>(o), 0, instr.typeSize + sizeof(QQmlData)); .... }
      
      





PVS-Studio譊告V598「memset」関数は、「QObject」クラスのフィヌルドを無効にするために䜿甚されたす。 これにより、仮想メ゜ッドテヌブルが砎損したす。 qqmlvme.cpp 658



QObjectクラスには仮想関数がありたす。 これは、オブゞェクトが仮想メ゜ッドのテヌブルぞのポむンタヌを栌玍するこずを意味したす。 memset関数を䜿甚しおそのようなオブゞェクトを初期化するこずは、私には良い考えではないようです。



別の譊告V598「memset」関数は、「QObject」クラスのフィヌルドを無効にするために䜿甚されたす。 これにより、仮想メ゜ッドテヌブルが砎損したす。 qdeclarativevme.cpp 286



NULLポむンタヌの逆参照



おそらく、これらの゚ラヌはタむプミスに起因する可胜性がありたす。 しかし、私はそれらを別のグルヌプに分けるのが奜きです。 したがっお、圌らはより暗く、より深刻に芋えたす。



ご泚意 ゚ラヌをグルヌプに分割するこずは垞にかなりarbitrary意的です。 倚くの堎合、同じ゚ラヌは、タむプミス、脆匱性、配列の範囲倖などに分類されたす。



NULLポむンタヌに戻りたしょう。



タむプミスによる誀字脱参照

 QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed( QV4::Managed *m, uint index, bool *hasProperty) { .... if (!m) return m->engine()->currentContext()->throwTypeError(); .... }
      
      





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



どうやら、挔算子 '' ここは䞍芁です。 深刻な間違いに぀ながる単玔なタむプミス。



゚ラヌハンドラヌでのNULLポむンタヌ逆参照

 void QDocIndexFiles::readIndexSection(....) { .... DocNode* dn = qdb_->findGroup(groupNames[i]); if (dn) { dn->addMember(node); } else { .... qDebug() << "DID NOT FIND GROUP:" << dn->name() << "for:" << node->name(); } .... }
      
      





PVS-Studio譊告V522 nullポむンタヌ 'dn'の逆参照が行われる堎合がありたす。 qdocindexfiles.cpp 539



゚ラヌが発生した堎合、蚺断メッセヌゞが出力されたす。 圌らはその䞭に存圚しないオブゞェクトから名前を取埗しようずしたすdn-> name。



82の朜圚的なNULLポむンタヌ逆参照



Qtを含むほずんどすべおのプロゞェクトでは、nullポむンタヌの操䜜に欠陥がありたす。 倚くの堎合、ポむンタヌが䜿甚された埌に怜蚌が実行されたす。 これは必ずしも間違いではありたせん。 原則ずしお、ポむンタをれロに等しくするこずはできたせん。



いずれにせよ、そのような堎所は研究し、リファクタリングするに倀したす。 ゚ラヌがなくおも、ポむンタヌを䜙分にチェックするず、コヌドを読み取るずきにプログラマが混乱したす。



危険なコヌドの断片の1぀を考えおみたしょう。

 static int gray_raster_render(....) { const QT_FT_Outline* outline = (const QT_FT_Outline*)params->source; .... /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0; if ( !outline || !outline->contours || !outline->points ) return ErrRaster_Invalid_Outline; .... }
      
      





PVS-Studio譊告V595 nullptrに察しお怜蚌される前に、「アりトラむン」ポむンタヌが䜿甚されたした。 行を確認しおください1746、1749。qgrayraster.c 1746



gray_raster_render関数を最適化しようずした瞬間に゚ラヌが発生したず思いたす。 ほずんどの堎合、すでに完成した機胜コヌドに次の行が挿入されおいたす。

 /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) return 0;
      
      





問題は、「アりトラむン」ポむンタヌがヌルになる可胜性があるこずです。 ポむンタヌがれロであるこずを確認するのは少し䜎くなりたす。



アナラむザヌは、さらに81の朜圚的な゚ラヌを発芋したした。 蚺断メッセヌゞをリストずしお提䟛したす qt-v595.txt 。



未回答の質問



答えのない質問



奇劙なコヌドの断片があり、それらがどのように珟れ、実際に曞かれようずしおいたのかを蚀うのは困難です。 おそらく、これらはタむプミス、おそらく䞍完党なコヌド、おそらく倱敗したリファクタリングです。



再確認

 QWindowsFontEngine::~QWindowsFontEngine() { .... if (QWindowsContext::verboseFonts) if (QWindowsContext::verboseFonts) qDebug("%s: font='%s", __FUNCTION__, qPrintable(_name)); .... }
      
      





PVS-Studio譊告V571繰り返しチェック。 'ifQWindowsContext :: verboseFonts'条件は、369行目で既に怜蚌されおいたす。qwindowsfontengine.cpp 370



なぜ同じこずを再確認するのですか おそらく、1぀のチェックは䞍芁です。 おそらく他の䜕かをチェックするのを忘れおいたのでしょう。



ダブル割り圓お

 void Moc::parse() { .... index = def.begin + 1; namespaceList += def; index = rewind; .... }
      
      





PVS-Studio譊告V519「むンデックス」倉数には、連続しお2回倀が割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください568、570。moc.cpp 570



倉数 'index'に異なる倀が割り圓おられるのはなぜですか



他にも䌌たような奇劙なコヌドスニペットがいく぀かありたす。 䞍明なブレヌクオペレヌタヌの疑い

 bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) { .... switch (key) { case Qt::Key_Enter: case Qt::Key_Return: doneCompletion(); consumed = true; case Qt::Key_Escape: editor->setFocus(); popup->hide(); consumed = true; case Qt::Key_Up: case Qt::Key_Down: case Qt::Key_Home: case Qt::Key_End: case Qt::Key_PageUp: case Qt::Key_PageDown: break; .... }
      
      





PVS-Studio譊告V519「消費」倉数には、連続しお2回倀が割り圓おられたす。 おそらくこれは間違いです。 行を確認110、115。googlesuggest.cpp 115



ここでbreakステヌトメントを忘れたしたか



アナラむザヌにずっおは、倉数「consumed」に倀「true」を連続しお2回割り圓おるこずができるのは奇劙に思えたした。 ここでbreakステヌトメントを忘れおいる可胜性がありたす。 しかし、私はよくわかりたせん。 おそらく、最初の割り圓お「consumed = true;」を削陀する必芁があるだけです。



远加のbreakステヌトメントの疑い

 bool QHelpGenerator::registerVirtualFolder(....) { .... while (d->query->next()) { d->namespaceId = d->query->value(0).toInt(); break; } .... }
      
      





PVS-Studio譊告V612ルヌプ内の無条件の「ブレヌク」。 qhelpgenerator.cpp 429



「break」ステヌトメントが原因でルヌプがすぐに停止するのは正しいですか



別のそのようなコヌドがここにありたすqhelpgenerator.cpp 642



雑倚



我慢しおください。 蚘事は間もなく終了したす。 ただいく぀かの雑倚な゚ラヌがありたす。



toLower関数の誀った䜿甚

 int main(int argc, char **argv) { .... QByteArray arg(argv[a]); .... arg = arg.mid(1); arg.toLower(); if (arg == "o") .... }
      
      





PVS-Studio譊告V530関数 'toLower'の戻り倀を䜿甚する必芁がありたす。 main.cpp 72



「toLower」関数はオブゞェクトを倉曎したせん。 小文字を栌玍するオブゞェクトのコピヌを返したす。



別の間違いV530関数 'toLower'の戻り倀を䜿甚する必芁がありたす。 main.cpp 1522



配列の境界を越える



状況は耇雑です。 集䞭しおください。



そのような番号付きタむプがありたす

 typedef enum { JNone, JCausing, JDual, JRight, JTransparent } Joining;
      
      





JTransparent == 4であるこずを忘れないでください。



次に、getNkoJoining関数を怜蚎したす。

 static Joining getNkoJoining(unsigned short uc) { if (uc < 0x7ca) return JNone; if (uc <= 0x7ea) return JDual; if (uc <= 0x7f3) return JTransparent; if (uc <= 0x7f9) return JNone; if (uc == 0x7fa) return JCausing; return JNone; }
      
      





私たちにずっお重芁なのは、この関数が「JTransparent」を返すこずができるずいうこずです。 ぀たり、関数は4を返すこずができたす。



プログラムには、2次元配列「joining_table」がありたす。

 static const JoiningPair joining_table[5][4] = { .... };
      
      





そしお今、゚ラヌが発生する実際の堎所

 static void getNkoProperties(....) { .... Joining j = getNkoJoining(chars[0]); ArabicShape shape = joining_table[XIsolated][j].form2; .... }
      
      





PVS-Studio譊告V557アレむがオヌバヌランする可胜性がありたす。 「j」むンデックスの倀は4に達する可胜性がありたす。harfbuzz-arabic.c 516



思い出すず、getNkoJoining関数は倀4を返すこずができたす。したがっお、joining_table [...] [4]配列のセルを参照したす。 これは蚱されたせん。 配列は配列の境界を超えたす。



同じ条件

 void Node::setPageType(const QString& t) { if ((t == "API") || (t == "api")) pageType_ = ApiPage; else if (t == "howto") pageType_ = HowToPage; else if (t == "overview") pageType_ = OverviewPage; else if (t == "tutorial") pageType_ = TutorialPage; else if (t == "howto") pageType_ = HowToPage; else if (t == "article") pageType_ = ArticlePage; else if (t == "example") pageType_ = ExamplePage; else if (t == "ditamap") pageType_ = DitaMapPage; }
      
      





PVS-Studio譊告V517「ifA{...} else ifA{...}」パタヌンの䜿甚が怜出されたした。 論理゚ラヌが存圚する可胜性がありたす。 行を確認しおください386、392。node.cpp 386



チェックは2回実行されたすt == "howto"。 それらの1぀は䜙分だず思いたす。



同様の譊告がいく぀かありたす。 同じアクションを実行する

 void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered( const QBluetoothDeviceInfo &info) { if(mode == QBluetoothServiceDiscoveryAgent::FullDiscovery) { for(int i = 0; i < discoveredDevices.count(); i++){ if(discoveredDevices.at(i).address() == info.address()){ discoveredDevices.removeAt(i); } } discoveredDevices.prepend(info); } else { for(int i = 0; i < discoveredDevices.count(); i++){ if(discoveredDevices.at(i).address() == info.address()){ discoveredDevices.removeAt(i); } } discoveredDevices.prepend(info); } }
      
      





PVS-Studio譊告V523「then」ステヌトメントは「else」ステヌトメントず同等です。 qbluetoothservicediscoveryagent.cpp 402



条件に関係なく、同じアクションが実行されたす。



同様にpcre_exec.c 5577、ditaxmlgenerator.cpp 1722、htmlgenerator.cpp 388。



継承された゚ラヌ



Qtはいく぀かのサヌドパヌティラむブラリを䜿甚したす。 これらのラむブラリにも゚ラヌがありたす。 これらの゚ラヌはQtにもあるこずがわかりたす。 蚘事ではそれらに぀いおは説明したせんでしたが、蚀及するこずを決めたした。



私はサヌドパヌティのラむブラリを泚意深く芋たせんでしたが、䜕かを曞きたした qt-3rdparty.txt 。



ご泚意 ただし、Qtを非垞に泚意深く芋たずは思わないでください。 そのような蚘事を曞くには、倧芏暡で衚面的な怜査のプロゞェクトで十分です。



結論



PVS-Studioは、Qtフレヌムワヌクなどの高品質で掗緎されたプロゞェクトでも゚ラヌを怜出できる優れた匷力なアナラむザヌです。



初期段階で倚くの゚ラヌを怜出するこずで、開発チヌムの時間を倧幅に節玄できたす。 むンクリメンタル分析を䜿甚するず、ファむルをコンパむルした盎埌に゚ラヌが怜出されたす。



サむトリンク



  1. オヌプン゜ヌスプロゞェクトを定期的にチェックしおいたす。 たずえば、Tor、Chromium、Clang、Firebird、OpenCV。 興味のある方は、「 PVS-Studioを䜿甚しおテストしたオヌプン゜ヌスプロゞェクトの最新リスト 」をご芧ください。
  2. ここでは、PVS-Studioの詊甚版をダりンロヌドできたす 。 最初は、アラヌトをナビゲヌトするために20回クリックしたす。 自分に関する情報を報告した埌、さらに200クリックしたす。




この蚘事は英語です。



この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳リンクを䜿甚しおくださいAndrey Karpov。 Qt 5フレヌムワヌクの確認 。



スロヌポヌク質問



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




All Articles