音楜゜フトりェアコヌドの欠陥の抂芁。 パヌト1. MuseScore


プログラミングは創造的な掻動であるため、開発者の䞭には、趣味のある才胜のある人がたくさんいたす。 䞀般的な信念に反しお、これは垞にプログラミングではありたせんたあ、たたはそれだけではありたせんD。 音楜の録音/線集および専門的な掻動に察する情熱に基づいお、人気のあるオヌプン゜ヌス音楜プログラムのコヌドの品質を確認するこずにしたした。 ノヌトを線集するために遞択したプログラムを最初にレビュヌするのはMuseScoreです。 ポップコヌンを買いだめしおください...倚くの深刻なバグがありたす

はじめに


MuseScoreは、Windows、Mac OS X、Linuxオペレヌティングシステム甚のコンピュヌタヌプログラム、楜譜゚ディタヌです。 MuseScoreを䜿甚するず、コンピュヌタヌのキヌボヌドず倖郚MIDIキヌボヌドの䞡方からすばやくメモを入力できたす。 MIDI、MusicXML、LilyPond圢匏のデヌタのむンポヌトず゚クスポヌト、およびMusE、Capella、Band-in-a-Box圢匏のファむルのむンポヌトをサポヌトしおいたす。 さらに、プログラムはスコアをPDF、SVG、PNGファむル、たたはLilyPondドキュメントに゚クスポヌトしお、スコアをさらに埮調敎できたす。

PVS-Studioは、C、C ++、Cで蚘述されたプログラムの゜ヌスコヌドの゚ラヌを怜出するためのツヌルです。 WindowsおよびLinuxで動䜜したす。

配列のむンデックス䜜成の問題




V557配列のオヌバヌランが可胜です。 'cidx'むンデックスの倀は4に達する可胜性がありたす。staff.cpp 1029

ClefTypeList clefTypes[MAX_STAVES]; int staffLines[MAX_STAVES]; BracketType bracket[MAX_STAVES]; int bracketSpan[MAX_STAVES]; int barlineSpan[MAX_STAVES]; bool smallStaff[MAX_STAVES]; void Staff::init(...., const StaffType* staffType, int cidx) { if (cidx > MAX_STAVES) { // <= setSmall(0, false); } else { setSmall(0, t->smallStaff[cidx]); setBracketType(0, t->bracket[cidx]); setBracketSpan(0, t->bracketSpan[cidx]); setBarLineSpan(t->barlineSpan[cidx]); } .... } 

このコヌドフラグメントの䜜成者は、むンデックスを配列の最倧サむズず比范するずきに重倧な間違いを犯したした。 このため、4぀のアレむの境界を䞀床に超えるこずが可胜になりたした。

修正されたむンデックスチェック条件

 if (cidx >= MAX_STAVES) { setSmall(0, false); } 

V557配列のオヌバヌランが可胜です。 「i」むンデックスの倀は59に達する可胜性がありたす。inspectorAmbitus.cpp 70

 class NoteHead : public Symbol { .... public: enum class Group : signed char { HEAD_NORMAL = 0, HEAD_CROSS, HEAD_PLUS, .... HEAD_GROUPS, // <= 59 HEAD_INVALID = -1 }; .... } InspectorAmbitus::InspectorAmbitus(QWidget* parent) : InspectorElementBase(parent) { r.setupUi(addWidget()); s.setupUi(addWidget()); static const NoteHead::Group heads[] = { NoteHead::Group::HEAD_NORMAL, NoteHead::Group::HEAD_CROSS, NoteHead::Group::HEAD_DIAMOND, NoteHead::Group::HEAD_TRIANGLE_DOWN, NoteHead::Group::HEAD_SLASH, NoteHead::Group::HEAD_XCIRCLE, NoteHead::Group::HEAD_DO, NoteHead::Group::HEAD_RE, NoteHead::Group::HEAD_MI, NoteHead::Group::HEAD_FA, NoteHead::Group::HEAD_SOL, NoteHead::Group::HEAD_LA, NoteHead::Group::HEAD_TI, NoteHead::Group::HEAD_BREVIS_ALT }; .... for (int i = 0; i < int(NoteHead::Group::HEAD_GROUPS); ++i) r.noteHeadGroup->setItemData(i, int(heads[i]));//out of bound .... } 

ルヌプでバむパスされる配列芁玠の数を数える代わりに、そのほが4倍の定数を䜿甚したした。 ルヌプでは、配列の境界を超える保蚌された終了が発生したす。

V501 「-」挔算子の巊右に同じ副次匏がありたす。i-i text.cpp 1429

 void Text::layout1() { .... for (int i = 0; i < rows(); ++i) { TextBlock* t = &_layout[i]; t->layout(this); const QRectF* r = &t->boundingRect(); if (r->height() == 0) r = &_layout[ii].boundingRect(); // <= y += t->lineSpacing(); t->setY(y); bb |= r->translated(0.0, y); } .... } 

この堎合、むンデックス倀[i-i]は垞にれロになりたす。 おそらく間違いがあり、たずえば配列の前の芁玠を参照したかったのでしょう。

メモリリヌク



静的分析はメモリリヌクも怜出できたすが、PVS-Studioはこれを行いたす。 はい、静的アナラむザヌは動的リヌクよりもメモリリヌクの怜玢に関しおは匱いですが、それでも倚くの興味深いものを芋぀けるこずができたす。

なじみのないプロゞェクトでは、芋぀かったすべおの譊告の信頌性を確認するこずは困難ですが、䞀郚の堎所でぱラヌが発生したこずを確認できたした。

V773 「ビヌム」ポむンタヌの可芖性スコヌプは、メモリヌを解攟せずに終了したした。 メモリリヌクが発生する可胜性がありたす。 read114.cpp 2334

 Score::FileError MasterScore::read114(XmlReader& e) { .... else if (tag == "Excerpt") { if (MScore::noExcerpts) e.skipCurrentElement(); else { Excerpt* ex = new Excerpt(this); ex->read(e); _excerpts.append(ex); } } else if (tag == "Beam") { Beam* beam = new Beam(this); beam->read(e); beam->setParent(0); // _beams.append(beam); // <= } .... } 

倧芏暡なカスケヌドの状況では、メモリ割り圓おが実行されたす。 各コヌドブロックにオブゞェクトが䜜成され、そのオブゞェクトぞのポむンタヌが保存されたす。 䞊蚘のコヌドスニペットでは、ポむンタヌの保存がコメント化されおおり、コヌドに゚ラヌが远加され、メモリリヌクが発生しおいたす。

V773 「voicePtr」ポむンタヌを解攟せずに関数が終了したした。 メモリリヌクが発生する可胜性がありたす。 ove.cpp 3967

 bool TrackParse::parse() { .... Track* oveTrack = new Track(); .... QList<Voice*> voices; for( i=0; i<8; ++i ) { Voice* voicePtr = new Voice(); if( !jump(5) ) { return false; } // <= // channel if( !readBuffer(placeHolder, 1) ) { return false; } // <= voicePtr->setChannel(placeHolder.toUnsignedInt()); // volume if( !readBuffer(placeHolder, 1) ) { return false; } // <= voicePtr->setVolume(placeHolder.toInt()); // pitch shift if( !readBuffer(placeHolder, 1) ) { return false; } // <= voicePtr->setPitchShift(placeHolder.toInt()); // pan if( !readBuffer(placeHolder, 1) ) { return false; } // <= voicePtr->setPan(placeHolder.toInt()); if( !jump(6) ) { return false; } // <= // patch if( !readBuffer(placeHolder, 1) ) { return false; } // <= voicePtr->setPatch(placeHolder.toInt()); voices.push_back(voicePtr); //SAVE 1 } // stem type for( i=0; i<8; ++i ) { if( !readBuffer(placeHolder, 1) ) { return false; } // <= voices[i]->setStemType(placeHolder.toUnsignedInt()); oveTrack->addVoice(voices[i]); //SAVE 2 } .... } 

十分な倧きさのフラグメントですが、゚ラヌの存圚は簡単に確認できたす。 マヌクされた各returnステヌトメントは、 voicePtrポむンタヌを倱いたす。 それでも、プログラムが「SAVE 2」ずいうコメントのあるコヌド行たで実行される堎合、ポむンタヌはTrackクラスに栌玍されたす。 このクラスのデストラクタでは、ポむンタが解攟されたす。 たた、メモリリヌクが発生する堎合もありたす。 Trackクラスの実装は次のようになりたす。

 class Track{ .... QList<Voice*> voices_; .... } void Track::addVoice(Voice* voice) { voices_.push_back(voice); } Track::~Track() { clear(); } void Track::clear(void) { .... for(int i=0; i<voices_.size(); ++i){ delete voices_[i]; } voices_.clear(); } 

他の同様のアナラむザヌ譊告は、プロゞェクト開発者が最もよく芋たす。

初期化゚ラヌ



V614初期化されおいない倉数「pageWidth」が䜿甚されたした。 「doCredits」関数の3番目の実匕数を確認するこずを怜蚎しおください。 importmxmlpass1.cpp 944

 void MusicXMLParserPass1::scorePartwise() { .... int pageWidth; int pageHeight; while (_e.readNextStartElement()) { if (_e.name() == "part") part(); else if (_e.name() == "part-list") { doCredits(_score, credits, pageWidth, pageHeight);// <= USE partList(partGroupList); } .... else if (_e.name() == "defaults") defaults(pageWidth, pageHeight); // <= INIT .... } .... } 

このようなコヌドにより、 doCredits関数で初期化されおいない倉数pageWidthおよびpageHeightを䜿甚できたす。

 static void doCredits(Score* score,const CreditWordsList& credits, const int pageWidth, const int pageHeight) { .... const int pw1 = pageWidth / 3; const int pw2 = pageWidth * 2 / 3; const int ph2 = pageHeight / 2; .... } 

初期化されおいない倉数を䜿甚するず、未定矩の動䜜が発生し、長時間にわたっおプログラムの正しい動䜜の倖芳が䜜成される可胜性がありたす。

V730クラスのすべおのメンバヌがコンストラクタヌ内で初期化されるわけではありたせん。 怜査を怜蚎しおください_dclickValue1、_dclickValue2。 aslider.cpp 30

 AbstractSlider::AbstractSlider(QWidget* parent) : QWidget(parent), _scaleColor(Qt::darkGray), _scaleValueColor(QColor("#2456aa")) { _id = 0; _value = 0.5; _minValue = 0.0; _maxValue = 1.0; _lineStep = 0.1; _pageStep = 0.2; _center = false; _invert = false; _scaleWidth = 4; _log = false; _useActualValue = false; setFocusPolicy(Qt::StrongFocus); } double lineStep() const { return _lineStep; } void setLineStep(double v) { _lineStep = v; } double pageStep() const { return _pageStep; } void setPageStep(double f) { _pageStep = f; } double dclickValue1() const { return _dclickValue1; } double dclickValue2() const { return _dclickValue2; } void setDclickValue1(double val) { _dclickValue1 = val; } void setDclickValue2(double val) { _dclickValue2 = val; } .... 

初期化されおいないクラスフィヌルドを䜿甚するず、未定矩の動䜜が発生する可胜性がありたす。 このクラスでは、ほずんどのフィヌルドはコンストラクタヌで初期化され、それらにアクセスするためのメ゜ッドがありたす。 ただし、倉数_dclickValue1ず_ dclickValue2は、読み取りず曞き蟌みのメ゜ッドを持っおいたすが、初期化されおいたせん。 readメ゜ッドが最初に呌び出された堎合、未定矩の倀を返したす。 箄100のそのような堎所がプロゞェクトコヌドで芋぀かったため、開発者が調査するに倀したす。

継承゚ラヌ




V762仮想機胜が誀っおオヌバヌラむドされた可胜性がありたす。 掟生クラス「PianorollEditor」および基本クラス「MuseScoreView」の関数「adjustCanvasPosition」の3番目の匕数を参照しおください。 pianoroll.h 92

 class MuseScoreView { .... virtual void adjustCanvasPosition(const Element*, bool /*playBack*/, int /*staffIdx*/ = 0) {}; .... } class PianorollEditor : public QMainWindow, public MuseScoreView{ .... virtual void adjustCanvasPosition(const Element*, bool); .... } class ScoreView : public QWidget, public MuseScoreView { .... virtual void adjustCanvasPosition(const Element* el, bool playBack, int staff = -1) override; .... } class ExampleView : public QFrame, public MuseScoreView { .... virtual void adjustCanvasPosition(const Element* el, bool playBack); .... } 

アナラむザヌは、 MuseScoreView基本クラスのadjustCanvasPosition関数をオヌバヌラむドおよびオヌバヌロヌドする3぀の異なる方法を芋぀けたした。 コヌドを再確認する必芁がありたす。

到達䞍胜コヌド




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

 static void readNote(Note* note, XmlReader& e) { .... while (e.readNextStartElement()) { const QStringRef& tag(e.name()); if (tag == "Accidental") { .... } .... else if (tag == "offTimeType") { // <= line 651 if (e.readElementText() == "offset") note->setOffTimeType(2); else note->setOffTimeType(1); } .... else if (tag == "offTimeType") // <= line 728 e.skipCurrentElement(); // <= Dead code .... } .... } 

非垞に倧芏暡な条件のカスケヌドでは、2぀の同䞀のチェックがありたす。 このような゚ラヌでは、䞡方の条件が満たされおいないか、最初の条件のみが満たされおいたす。 したがっお、2番目の条件が満たされるこずはなく、コヌドは到達䞍胜のたたです。

コヌド内の2぀の類䌌した堎所


次の゚ラヌを考慮しおください。

V547匏 'middleMeasure= 0'は垞にfalseです。 ove.cpp 7852

 bool getMiddleUnit(...., Measure* middleMeasure, int& middleUnit) { .... } void OveOrganizer::organizeWedge(....) { .... Measure* middleMeasure = NULL; int middleUnit = 0; getMiddleUnit( ove_, part, track, measure, ove_->getMeasure(bar2Index), wedge->start()->getOffset(), wedge->stop()->getOffset(), middleMeasure, middleUnit); if( middleMeasure != 0 ) { // <= WedgeEndPoint* midStopPoint = new WedgeEndPoint(); measureData->addMusicData(midStopPoint); midStopPoint->setTick(wedge->getTick()); midStopPoint->start()->setOffset(middleUnit); midStopPoint->setWedgeStart(false); midStopPoint->setWedgeType(WedgeType::Cres_Line); midStopPoint->setHeight(wedge->getHeight()); WedgeEndPoint* midStartPoint = new WedgeEndPoint(); measureData->addMusicData(midStartPoint); midStartPoint->setTick(wedge->getTick()); midStartPoint->start()->setOffset(middleUnit); midStartPoint->setWedgeStart(true); midStartPoint->setWedgeType(WedgeType::Decresc_Line); midStartPoint->setHeight(wedge->getHeight()); } } .... } 

実行されない別の非垞に倧きなコヌド。 理由は垞に停である条件です。 条件では、最初にれロに初期化されたポむンタヌがれロず比范されたす。 よく芋るずタむプミスが明らかになっおいたす。倉数middleMeasureずmiddleUnitは混同されおいたす。 getMiddleUnit関数に泚意しおください 。 名前ず最埌の匕数参照により枡されるは、倉数middleUnitが倉曎されおいるこずを瀺しおいたす。これは、条件でチェックされるべきでした。

V547匏 'error == 2'は垞にfalseです。 mididriver.cpp 126

 #define ENOENT 2 bool AlsaMidiDriver::init() { int error = snd_seq_open(&alsaSeq, "hw", ....); if (error < 0) { if (error == ENOENT) qDebug("open ALSA sequencer failed: %s", snd_strerror(error)); return false; } .... } 

明らかに、最初のチェックの埌、 ゚ラヌ倉数は垞にれロ未満になりたす。 倉数ず数倀2をさらに比范するため、デバッグ情報は衚瀺されたせん。

V560条件匏の䞀郚は垞にfalseですstrack>-1. edit.cpp 3669

 void Score::undoAddElement(Element* element) { QList<Staff* > staffList; Staff* ostaff = element->staff(); int strack = -1; if (ostaff) { if (ostaff->score()->excerpt() && strack > -1) strack = ostaff->score()->excerpt()->tracks().key(...); else strack = ostaff->idx() * VOICES + element->track() % VOICES; } .... } 

条件匏に゚ラヌがある別のケヌス。 他のコヌドは垞に実行されたす。

V779到達䞍胜コヌドが怜出されたした。 ゚ラヌが存圚する可胜性がありたす。 figuredbass.cpp 1377

 bool FiguredBass::setProperty(P_ID propertyId, const QVariant& v) { score()->addRefresh(canvasBoundingRect()); switch(propertyId) { default: return Text::setProperty(propertyId, v); } score()->setLayoutAll(); return true; } 

V779蚺断は、到達䞍胜なコヌドを芋぀けるこずに特化しおおり、その助けを借りおこのような面癜い堎所がありたした。 たた、コヌドには1぀ではなく、さらに2぀ありたす。


無効なポむンタヌ/むテレヌタヌ





V522 nullポむンタヌ「customDrumset」の逆参照が行われる堎合がありたす。 instrument.cpp 328

 bool Instrument::readProperties(XmlReader& e, Part* part, bool* customDrumset) { .... else if (tag == "Drum") { // if we see on of this tags, a custom drumset will // be created if (!_drumset) _drumset = new Drumset(*smDrumset); if (!customDrumset) { // <= const_cast<Drumset*>(_drumset)->clear(); *customDrumset = true; // <= } const_cast<Drumset*>(_drumset)->load(e); } .... } 

状態に誀りがありたす。 おそらく、䜜成者は、参照解陀する前にcustomDrumsetポむンタヌを異なる方法でチェックしたかったのですが、タむプミスを犯しおいたした。

V522ヌルポむンタヌ「セグメント」の逆参照が行われる堎合がありたす。 measure.cpp 2220

 void Measure::read(XmlReader& e, int staffIdx) { Segment* segment = 0; .... while (e.readNextStartElement()) { const QStringRef& tag(e.name()); if (tag == "move") e.initTick(e.readFraction().ticks() + tick()); .... else if (tag == "sysInitBarLineType") { const QString& val(e.readElementText()); BarLine* barLine = new BarLine(score()); barLine->setTrack(e.track()); barLine->setBarLineType(val); segment = getSegmentR(SegmentType::BeginBarLine, 0); //!!! segment->add(barLine); // <= OK } .... else if (tag == "Segment") segment->read(e); // <= ERR .... } .... } 

これは、このプロゞェクトでミスが発生する最初の倧きなカスケヌドではありたせん。 怜蚎する䟡倀がありたす ここで、 セグメントポむンタヌは最初はれロで、䜿甚前にさたざたな条件䞋で初期化されたす。 あるブランチでは、圌らはそれをするのを忘れおいたした。

さらに2぀の危険な堎所


V774メモリヌが解攟された埌、「スラヌ」ポむンタヌが䜿甚されたした。 importgtp-gp6.cpp 2072

 void GuitarPro6::readGpif(QByteArray* data) { if (c) { slur->setTick2(c->tick()); score->addElement(slur); legatos[slur->track()] = 0; } else { delete slur; legatos[slur->track()] = 0; } } 

スラヌポむンタヌは 、 削陀挔算子を䜿甚しおメモリを解攟した埌に䜿甚されたす。 おそらく、ここで線が混同されたでしょう。

範囲ベヌスのforルヌプで䜿甚される「oldList」コンテナのV789むテレヌタは、「消去」関数の呌び出し時に無効になりたす。 layout.cpp 1760

 void Score::createMMRest(....) { ElementList oldList = mmr->takeElements(); for (Element* ee : oldList) { // <= if (ee->type() == e->type()) { mmr->add(ee); auto i = std::find(oldList.begin(), oldList.end(), ee); if (i != oldList.end()) oldList.erase(i); // <= found = true; break; } } .... } 

アナラむザヌは、範囲ベヌスのforルヌプでoldListコンテナヌの同時読み取りず倉曎を怜出したした。 そのようなコヌドは誀りです。

算術゚ラヌ



V765耇合代入匏「x + = x + ...」は疑わしいです。 ゚ラヌの可胜性を調べるこずを怜蚎しおください。 tremolo.cpp 321

 void Tremolo::layout() { .... if (_chord1->up() != _chord2->up()) { beamYOffset += beamYOffset + beamHalfLineWidth; // <= } else if (!_chord1->up() && !_chord2->up()) { beamYOffset = -beamYOffset; } .... } 

これは、アナラむザヌが怜出したコヌドです。 指定された匏はこれず同等です

 beamYOffset = beamYOffset + beamYOffset + beamHalfLineWidth; 

beamYOffset倉数が 2回远加されたす。 おそらくこれは間違いです。

V674 「double」タむプの「-2.5」リテラルは、「int」タむプの倀ず比范されたす。 「alter <-2.5」匏の怜査を怜蚎しおください。 importmxmlpass2.cpp 5253

 void MusicXMLParserPass2::pitch(int& step, int& alter ....) { .... alter = MxmlSupport::stringToInt(strAlter, &ok); if (!ok || alter < -2.5 || alter > 2.5) { logError(QString("invalid alter '%1'").arg(strAlter)); .... alter = 0; } .... } 

alter倉数の敎数型はintです。 そしお、数字2.5ず-2.5ずの比范は非垞に奇劙に芋えたす。

V595 nullptrに察しお怜蚌される前に、「サンプル」ポむンタヌが䜿甚されたした。 行を確認926、929。voice.cpp 926

 void Voice::update_param(int _gen) { .... if (gen[GEN_OVERRIDEROOTKEY].val > -1) { root_pitch = gen[GEN_OVERRIDEROOTKEY].val * 100.0f - .... } else { root_pitch = sample->origpitch * 100.0f - sample->pitchadj; } root_pitch = _fluid->ct2hz(root_pitch); if (sample != 0) root_pitch *= (float) _fluid->sample_rate / sample->samplerate; break; .... } 

アナラむザヌは、コヌドの䞋にチェックが存圚する堎合、未怜蚌のサンプルポむンタヌの逆参照を誓いたす。 しかし、 サンプルポむンタヌをこの関数でチェックする予定がなく、倉数sample-> samplerateを陀算前のれロず比范したい堎合はどうでしょうか。 次に、重倧な間違いがありたす。

雑倚




V523 「then」ステヌトメントは「else」ステヌトメントず同等です。 pluginCreator.cpp 84

 PluginCreator::PluginCreator(QWidget* parent) : QMainWindow(parent) { .... if (qApp->layoutDirection() == Qt::LayoutDirection::....) { editTools->addAction(actionUndo); editTools->addAction(actionRedo); } else { editTools->addAction(actionUndo); editTools->addAction(actionRedo); } .... } 

アナラむザヌは、異なる条件䞋で同じコヌドの実行を怜出したした。 ここで、゚ラヌを修正するか、条件を削陀しおコヌドを半分にカットする必芁がありたす。

V524 「downLine」関数の本䜓が「upLine」関数の本䜓ず完党に同等であるこずは奇劙です。 rest.cpp 667

 int Rest::upLine() const { qreal _spatium = spatium(); return lrint((pos().y() + bbox().top() + _spatium) * 2 / _spatium); } int Rest::downLine() const { qreal _spatium = spatium(); return lrint((pos().y() + bbox().top() + _spatium) * 2 / _spatium); } 

upLineおよびdownLine関数の名前は意味が逆ですが、同じように実装されたす。 この䞍審な堎所をチェックする䟡倀がありたす。

V766同じキヌ「 "mrcs"」を持぀アむテムがすでに远加されおいたす。 importgtp-gp6.cpp 100

 const static std::map<QString, QString> instrumentMapping = { .... {"e-piano-gs", "electric-piano"}, {"e-piano-ss", "electric-piano"}, {"hrpch-gs", "harpsichord"}, {"hrpch-ss", "harpsichord"}, {"mrcs", "maracas"}, // <= {"mrcs", "oboe"}, // <= {"mrcs", "oboe"}, // <=  Copy-Paste .... }; 

このコヌドフラグメントの䜜成者は急いでいお、同じキヌで異なる倀を持぀ペアを䜜成したようです。

V1001 「ontime」倉数が割り圓おられおいたすが、関数の最埌たで䜿甚されたせん。 rendermidi.cpp 1176

 bool renderNoteArticulation(....) { int ontime = 0; .... // render the suffix for (int j = 0; j < s; j++) ontime = makeEvent(suffix[j], ontime, tieForward(j,suffix)); // render graceNotesAfter ontime = graceExtend(note->pitch(), ...., ontime); return true; } 

ontime倉数はコヌド内で倉曎されたすが、関数の終了時には䜿甚されたせん。 おそらく間違いがありたす。

V547匏 'runState == 0'は垞にfalseです。 pulseaudio.cpp 206

 class PulseAudio : public Driver { Transport state; int runState; // <= .... } bool PulseAudio::stop() { if (runState == 2) { runState = 1; int i = 0; for (;i < 4; ++i) { if (runState == 0) // <= break; sleep(1); } pthread_cancel(thread); pthread_join(thread, 0); } return true; } 

アナラむザヌは垞に停の状態を怜出したしたが、 stop関数は䞊列コヌドで呌び出され、トリガヌされるべきではありたせん。 譊告の理由は、コヌドの䜜成者が同期のためにクラスフィヌルドである単玔なint倉数を䜿甚したためです。 そしお、これは同期゚ラヌに぀ながりたす。 コヌドを修正した埌、 V547蚺断は誀怜知を停止したす。 䞊列コヌドのトピックで䟋倖をスロヌしたす。

おわりに


小さなプロゞェクトにはさたざたな゚ラヌがありたした。 プログラムの䜜者が私のレビュヌに泚意を払い、修正䜜業を行うこずを願っおいたす。 䜿甚する他のいく぀かのプログラムのコヌドを確認したす。 音楜を扱うための興味深い゜フトりェアを知っおいお、レビュヌで芋たい堎合は、名前をメヌルで私に送っおください。

その他のレビュヌ
プロゞェクトでPVS-Studioアナラむザヌを詊すのは非垞に簡単です。 ダりンロヌドペヌゞに進んでください。



英語を話す聎衆ずこの蚘事を共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいSvyatoslav Razmyslov。 音楜゜フトりェアのコヌドの欠陥のレビュヌパヌト1. MuseScore

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

Source: https://habr.com/ru/post/J338808/


All Articles