Image1.png>„> xmage este o aplica╚Ťie / server client pentru a juca magie : Adunarea (MTG). Xmage a ├«nceput s─â evolueze la ├«nceputul anului 2010. ├Än acest timp au fost publicate 182 de versiuni, o armat─â ├«ntre ├«ntreb─âtoare a ├«nt├ólnit ╚Öi proiectul se dezvolt─â ├«n mod activ. O oportunitate excelent─â de a participa ╚Öi la dezvoltarea sa! Prin urmare, ast─âzi, Unicornul PVS-Studio va verifica baza de cod Xmage ╚Öi cine ╚Ötie, ar putea intra ├«n conflict cu cineva ├«n lupt─â.  </p>
<h2> Pe scurt pe proiect </h2>
<p> Xmage a fost dezvoltat activ timp de 10 ani. Scopul s─âu este de a crea o versiune online gratuit─â ╚Öi o carte open source joc Magic: adunarea ini╚Ťial─â. </p>
<p> </p>
<ul>
<li> Acces la aproximativ 19.000 de h─âr╚Ťi unice emise ├«n timpul celor 20 de ani de istoric MTG; </li>
<li> control automat și aplicare a tuturor regulilor jocului existent; </li>
<li> (AI); </li>
<li> (standard, modern, vintage, comand─â); </li>
<li> </li>
</ul>
<p> Am c─âzut pe activitatea studen╚Ťilor de la Universitatea de Tehnologie Delft (Master of Arhitectur─â Software). Aceasta a constat c─â b─âie╚Ťii au f─âcut parte activ─â ├«n proiecte open source, care trebuiau s─â fie destul de complexe ╚Öi s─â se dezvolte ├«n mod activ. Pe o perioad─â de opt s─âpt─âm├óni, studen╚Ťii au studiat cursul ╚Öi proiectele open source pentru a ├«n╚Ťelege ╚Öi descrie arhitectura software-ului selectat. <br /> Deci, asta-i tot. ├Än aceast─â lucrare, b─âie╚Ťii au analizat proiectul Xmage ╚Öi unul dintre aspectele muncii lor a fost acela de a ob╚Ťine diferite valori folosind sonarqube (num─âr de linii de cod, complexitate ciclomatic, duplicare de cod, miros de cod, erori, vulnerabilit─â╚Ťi etc.). <br /> Aten╚Ťia mea a fost atras─â de faptul c─â, la momentul anului 2018, analiza sonarqube a ar─âtat 700 de defecte (bug-uri, vulnerabilit─â╚Ťi) pentru 1000000 de linii de cod. <br /> Dup─â ce am c─âutat ├«n istoria contribuabililor, am descoperit c─â din raportul primit cu avertismente, au f─âcut o cerere de tragere pentru a corecta aproximativ 30 de defecte din categoria „Blocker” sau „critic”. Ce zici de restul avertismentelor nu este cunoscut, dar sper c─â nu au fost rata╚Ťi. <br /> A fost de 2 ani de c├ónd ╚Öi baza de cod a crescut cu aproximativ 250.000 de linii de cod – un motiv bun pentru a vedea cum se ├«nt├ómpl─â lucrurile.  </p>
<h2> Despre analiza </h2>
<p> Pentru analiz─â, am luat versiunea Xmage – 1.4.44v0. <br /> Am fost foarte norocos cu proiectul. Cl─âdirea Xmation cu Maven sa dovedit foarte simpl─â (a╚Öa cum a fost scris─â ├«n documenta╚Ťie):  </p>
<pre><code>mvn clean install -DskipTests</code></pre>
<p> Nimic mai mult a fost cerut de la mine. Misto? <br /> Integrarea pluginului PVS-Studio ├«n Maven nu are nici o problem─â: totul este ca ├«n documenta╚Ťie. <br /> Dup─â analiz─â, au fost primite 911 avertismente, inclusiv 674 pentru avertismente de 1 ╚Öi 2 nivele de ├«ncredere. ├Än sensul prezentului articol, nu am luat ├«n considerare avertismentele de nivel 3 deoarece exist─â, de obicei, un procent ridicat de fals pozitive. A╚Ö dori s─â v─â atrag aten╚Ťia asupra faptului c─â atunci c├ónd utiliza╚Ťi un analizor static ├«ntr-o b─ât─âlie real─â, nu pute╚Ťi ignora astfel de avertismente deoarece pot indica, de asemenea, defecte semnificative din Cod. <br /> ├Än plus, nu am luat ├«n considerare avertismentele privind anumite reguli pe motiv c─â acestea sunt mai bine luate ├«n considerare de cei care cunosc proiectul ca mine:  </p>
<ul>
<li> V6022, /. 336. </li>
<li> v6014 ,,, 73. </li>
<li> v6021 ,,. 36. </li>
<li> v6048 ,,. 17. </li>
</ul>
<p> ├Än plus, mai multe reguli de diagnosticare au produs aproximativ 20 de false pozitive evidente de acela╚Öi tip. Salvat ├«n todo! <br /> ├«n consecin╚Ť─â, dac─â sc─âdem totul, aproximativ 190 pozitive mi-au fost prezentate pentru examinare. <br /> C├ónd se iau ├«n considerare declan╚Öatoarele, au fost identificate multe defecte minore de acela╚Öi tip, care erau fie legate de depanare, fie de o verificare sau o opera╚Ťiune f─âr─â sens. ├Än plus, multe pozitive au fost asociate cu o bucat─â foarte ciudat─â de cod care a fost respins─â. <br /> ├Än consecin╚Ť─â, pentru acest articol, am identificat 11 reguli de diagnosticare ╚Öi am analizat unul dintre cele mai interesante declan╚Öatoare. <br /> S─â arunc─âm o privire la ceea ce sa ├«nt├ómplat.  </p>
<h2> N1 AVERTISMENT </h2>
<p> V6003 Utilizarea modelului „Dac─â (card! = null) {…} altfel dac─â (card! = null) {…}” a fost detectat. Exist─â o probabilitate de prezen╚Ť─â de eroare logic─â. Torrentialgearhulk.Java (90), torrentialGearhulk.java (102)  </p>
<pre><code>@Overridepublic boolean apply(Game game, Ability source) { .... Card card = game.getCard(....); if (card != null) { .... } else if (card != null) { .... } ....}</code></pre>
<h2> N2 AVERTISMENT </h2>
<p> V6004 Instruc╚Ťiunea „Atunci” este echivalent─â cu instruc╚Ťiunea „altceva”. AsthoughefffectImpl.java (35), AsthougheffectImpl.java (37)  </p>
<pre><code>@Overridepublic boolean applies(....) { // affectedControllerId = player to check if (getAsThoughEffectType().equals(AsThoughEffectType.LOOK_AT_FACE_DOWN)) { return applies(objectId, source, playerId, game); } else { return applies(objectId, source, playerId, game); }}</code></pre>
<p> O eroare comun─â care a avut loc ├«n practica mea de verificare a proiectelor open source. Copiaza si lipeste? Sau mi-e dor de ceva? Cred c─â trebuie ├«nc─â s─â v─â ├«ntoarce╚Ťi falsi la ramurala. PS Dac─â nu exist─â nici un apel recursiv (….), deoarece acestea sunt diferite metode. Trigger similar: <╬╝l> </p>
<li> v6004 Instruc╚Ťiunea „Atunci” este echivalent─â cu declara╚Ťia „altceva”. GUIDISAPLAYUTL.java (194), GAIDISPLAYUTL.java (198) </li>
</ul>
<p> Tolowowercase (local.English) .Startswith („fiecare”) este ├«ntotdeauna gre╚Öit. SetpowertoupendnessAffect.java (107)  </p>
<pre><code>@Overridepublic String getText(Mode mode) { StringBuilder sb = new StringBuilder(); .... if (filter.getMessage().toLowerCase(Locale.ENGLISH).startsWith(

Reguli de diagnosticare Triggers V6007 sunt foarte populare pentru fiecare proiect verificat. Xmage nu este o excep╚Ťie (79 buc─â╚Ťi). Ac╚Ťionarea regulii, ├«n principiu, totul este cazul, dar multe cazuri se refer─â la depanare, apoi pe reasigurare, apoi pe altceva. ├Än general, este mai bine ca autorul codului s─â monitorizeze astfel de pozitive dec├ót pentru mine.
Acest declan╚Öator, cu toate acestea, este cu siguran╚Ť─â o eroare. ├Än func╚Ťie de pornirea liniei Filter.GetMessage () la textul SBLE „A …” sau „au …” se adaug─â. Dar eroarea este c─â dezvoltatorii verific─â dac─â lan╚Ťul ├«ncepe cu o liter─â de capital, dup─â conversia aceluia╚Öi lan╚Ť ├«n litere mici ├«nainte de aceasta. Oops. Ca rezultat, linia ad─âugat─â va fi ├«ntotdeauna „au …”. Rezultatul defec╚Ťiunii nu este critic─â, dar ╚Öi nepl─âcut: un analfabet de text compus va ap─ârea undeva. Punctele pozitive pe care le-am g─âsit cel mai interesant:

  • v6007 Expresia „t.Startswith (” – „) este ├«ntotdeauna fals─â. BOOSTSOURCEEFFECT.JAVA (103)
  • Expresia V6007 ‘SetNames.impty () este ├«ntotdeauna fals─â. Downloadpictureservice.java (300)
  • Expresia V6007 ‘ExpressionBucketName == Null „este ├«ntotdeauna gre╚Öit─â. S3Uploader.java (23)
  • v6007 expresie ‘! Lastrule.endswith („.”) Este ├«ntotdeauna adev─ârat. EFECTELY.JAVA (76)
  • Expresia V6007 ‘Subtipstoignore :: Con╚Ťine „este ├«ntotdeauna fals─â. VERIFYCARDDATEST.java (893)
  • Expresia V6007 „NotStartDateles == 1 ‘este ├«ntotdeauna fals─â. MageserverimpL.java (1330)

n4 AVERTISMENT

V6008 NULL DEREVEREA „SavespecialReres”. Dragonsmaze.java (230)

public final class DragonsMaze extends ExpansionSet { .... private List<CardInfo> savedSpecialRares = new ArrayList<>(); .... @Override public List<CardInfo> getSpecialRare() { if (savedSpecialRares == null) { // <= CardCriteria criteria = new CardCriteria(); criteria.setCodes("GTC").name("Breeding Pool"); savedSpecialRares.addAll(....); // <= criteria = new CardCriteria(); criteria.setCodes("GTC").name("Godless Shrine"); savedSpecialRares.addAll(....); .... } return new ArrayList<>(savedSpecialRares); }}

Analizorul se pl├ónge de dereferen╚Ťele de referin╚Ť─â NULL SAVEDSECialReres atunci c├ónd executarea atinge prima umplere a colec╚Ťiei.
Primul lucru care vine ├«n mintea mea este pur ╚Öi simplu pentru a confunda salvepecialrares == null cu salvateSpecialRes! = Null. Dar, ├«ntr-un astfel de caz, NPE poate ap─ârea ├«n constructorul arraylist atunci c├ónd colec╚Ťia este returnat─â de metod─â, deoarece salvelecialReres == Null este ├«ntotdeauna posibil. Corecta╚Ťi codul cu prima solu╚Ťie care vine ├«n mintea mea nu este o op╚Ťiune bun─â. Dup─â o mic─â ├«n╚Ťelegere a codului, am descoperit c─â ad secticolele sunt imediat definite de o colec╚Ťie goal─â atunci c├ónd este declarat─â ╚Öi nu este realocat─â ├«n alt─â parte. Acest lucru ne spune c├ót de multe ├«ntreb─âri nu vor fi niciodat─â zero, iar dereferen╚Ťele unei referin╚Ťe zero, al c─ârui analizor avertizeaz─â, nu se va ├«nt├ómpla niciodat─â, deoarece nu va ajunge niciodat─â la colec╚Ťie. Ca rezultat, metoda va returna ├«ntotdeauna o colec╚Ťie goal─â.
PS Pentru a rezolva aceast─â problem─â, trebuie s─â ├«nlocui╚Ťi SavespecpecialRes == Null de savespecpecialRes.Ascap─â ().
PPS din p─âcate, juc├ónd ├«n Xmage, nu ve╚Ťi putea ob╚Ťine c─âr╚Ťi rare speciale pentru colec╚Ťia Maze Dragon.
Un alt caz de dereferencerea unei referin╚Ťe zero:

  • V6008 Zero Dereference de „coresponden╚Ť─â”. Operatorul de tablecontroller.java (973)

V6012 Operator „:” Oricare ar fi expresia sa condi╚Ťionat─â, ├«ntoarce╚Ťi ├«ntotdeauna doar una ╚Öi aceea╚Öi valoare „table.getcreatetime ( ) „. TableManager.java (418), TableManager.java (418)

private void checkTableHealthState() { .... logger.debug(.... + formatter.format(table.getStartTime() == null ? table.getCreateTime() : table.getCreateTime()) + ....); ....}

Aici operatorul ternar?: Returneaz─â aceea╚Öi valoare indiferent de Table.GetStttime condi╚Ťie () == null. Cred c─â finalizarea codului a jucat o glum─â crud─â dezvoltatorului. Op╚Ťiunea de corec╚Ťie:

private void checkTableHealthState() { .... logger.debug(.... + formatter.format(table.getStartTime() == null ? table.getCreateTime() : table.getStartTime()) + ....); ....}

N6

AVERTISMENT

V6026 Aceast─â valoare este deja atribuit─â variabilei „Acest lucru „.Becreatetypetargetefect.java (54)

publicBecomesCreatureTypeTargetEffect(final BecomesCreatureTypeTargetEffect effect) { super(effect); this.subtypes.addAll(effect.subtypes); this.loseOther = effect.loseOther; this.loseOther = effect.loseOther;}

Lan╚Ť dublu de atribuire. Se pare c─â dezvoltatorul a fost pu╚Ťin purtat cu cheile de comenzi rapide ╚Öi nu a observat-o. Dar, deoarece efectul are un num─âr mare de zone, fragmentul merit─â s─â fie focalizat.

N7 AVERTISMENT

V6036 Valoarea op╚Ťiunii „Selects” non-ini╚Ťializate este utilizat─â. SESION.JAVA (227)

public String connectUserHandling(String userName, String password){ .... if (!selectUser.isPresent()) { // user already exists selectUser = UserManager.instance.getUserByName(userName); if (selectUser.isPresent()) { User user = selectUser.get(); .... } } User user = selectUser.get(); // <= ....}

De la avertizarea analizorului, putem concluziona c─â selec╚Ťia.get () poate lansa o nosuchelement.
Să arătăm mai îndeaproape ceea ce se întâmplă aici.
Dac─â crede╚Ťi c─â comentariul pe care utilizatorul ├«l exist─â deja, nicio excep╚Ťie nu va fi ridicat─â:

....if (!selectUser.isPresent()) { // user already exists ....}User user = selectUser.get()....

├«n acest caz, execu╚Ťia programului n ‘nu intr─â ├«n corp de instruire condi╚Ťionat─â. ╚śi totul va fi bine. Dar apoi apare ├«ntrebarea: de ce avem nevoie de un operator condi╚Ťionat cu un fel de logic─â complex─â dac─â nu este niciodat─â executat─â?
Dar ce se întâmplă dacă comentariul nu este nimic?

....if (!selectUser.isPresent()) { // user already exists selectUser = UserManager.instance.getUserByName(userName); if (selectUser.isPresent()) { .... }}User user = selectUser.get(); // <=....

Apoi, execu╚Ťia intr─â ├«n corpul instruc╚Ťiunii condi╚Ťionate ╚Öi recupereaz─â utilizatorul prin Geruserbyname (). Valabilitatea utilizatorului este verificat─â din nou, suger├ónd c─â selec╚Ťia nu poate fi ini╚Ťializat─â. Nu exist─â alt─â ramur─â pentru acest caz, ceea ce va duce, de asemenea, la o nosuchelementexcep╚Ťia pe linia de cod ├«n cauz─â.

N8 AVERTISMENT

V6042 Compatibilitatea expresiei cu tipul „A” este verificat─â, dar este convertit─â ├«n tipul „B”. Checkboxlist.java (586)

/** * sets the model - must be an instance of CheckBoxListModel * * @param model the model to use * @throws IllegalArgumentException if the model is not an instance of * CheckBoxListModel * @see CheckBoxListModel */@Overridepublic void setModel(ListModel model) { if (!(model instanceof CheckBoxListModel)) { if (model instanceof javax.swing.DefaultListModel) { super.setModel((CheckBoxListModel)model); // <= } else { throw new IllegalArgumentException( "Model must be an instance of CheckBoxListModel!"); } } else { super.setModel(model); }}

Autorul codului este confuz despre ceva aici: mai ├«nt├ói el asigur─â c─â modelul n ‘nu este un checkboxlistmodel, atunci , converte╚Öte ├«n mod explicit obiectul ├«n acest tip. Din acest motiv, metoda SetModel va lansa imediat o clas─â de clas─â atunci c├ónd ajunge acolo.
Fișierul CheckboxList.java a fost adăugat acum 2 ani și acest bug persistă în codul Incepand de la. Aparent, nu există teste pentru setări incorecte, nu există o utilizare reală a acestei metode cu tipuri de tipuri inadecvate, așa că trăiește.
Dac─â dintr-o dat─â cineva se conecteaz─â la aceast─â metod─â ╚Öi cite╚Öte Javadoc, el se va a╚Ötepta la o vizibilitate ilegalargumentexcep╚Ťia … Nu cred c─â cineva coloc─â ├«n mod deliberat cu aceast─â excep╚Ťie, dar cine ╚Ötie.
Av├ónd ├«n vedere documenta╚Ťia, codul ar trebui s─â arate cel mai probabil:

public void setModel(ListModel model) { if (!(model instanceof CheckBoxListModel)) { throw new IllegalArgumentException( "Model must be an instance of CheckBoxListModel!"); } else { super.setModel(model); }}

avertizare n9

V6060 „referin╚Ť─â” „A fost folosit ├«nainte de a fi verificat ├«mpotriva nullului. Vigeanintuition.java (79), Vigeanintuition.java (78)

V6060 avertizeaz─â dezvoltatorul Un obiect este accesul ├«nainte de a nu fi verificat pentru nul. Declan╚Öatoarele acestei reguli sunt adesea g─âsite ├«n articolele privind auditul proiectului open source: ├«n general motivul este e╚Öecul reflectoriz─ârii sau modificarea contractelor de metode. Dac─â acorda╚Ťi aten╚Ťie metodei GetPlayer (), atunci totul va seta imediat:

// Result must be checked for null.// Possible errors search pattern: (\S*) = game.getPlayer.+\n(?!.+\1 != null)Player getPlayer(UUID playerId);

N10 AVERTISMENT

V6072 Dou─â fragmente de cod similare a fost g─âsit. Aceasta poate fi o eroare de tastare, iar variabila „Playerb” ar trebui utilizat─â ├«n locul „Playera”. SubtiphanggeffectStest.java (162), subtiphanghangeffectstest.java (156), subtiphangefffectstest.java (160)

@Testpublic void testArcaneAdaptationGiveType() { addCard(Zone.HAND, playerA, "Arcane Adaptation", 1); // Enchantment {2}{U} addCard(Zone.BATTLEFIELD, playerA, "Island", 3); addCard(Zone.HAND, playerA, "Silvercoat Lion"); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion"); // <= addCard(Zone.HAND, playerB, "Silvercoat Lion"); addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion"); // <= .... for (Card card : playerB.getGraveyard().getCards(currentGame)) { if (card.isCreature()) { Assert.assertEquals(card.getName() + " should not have ORC type", false, card.getSubtype(currentGame).contains(SubType.ORC)); Assert.assertEquals(card.getName() + " should have CAT type", true, card.getSubtype(currentGame).contains(SubType.CAT)); } }}

Dup─â ce a╚Ťi observat c─â aceast─â eroare este ├«n Teste, pute╚Ťi devaloriza imediat defec╚Ťiunea g─âsit─â ├«n g├óndire: „Ei bine, acestea sunt teste”. Dac─â este cazul, nu sunt de acord cu tine. La urma urmei, testele joac─â un rol destul de important ├«n dezvoltare (dar nu la fel de vizibil ca programarea) ╚Öi c├ónd apare o eroare ├«ntr-o versiune, ace╚Ötia ├«ncep imediat s─â indice testele / testerele. Astfel, testele defecte sunt incontestabile. De ce sunt necesare astfel de teste? De ce s─â de╚Öeuri resursele pe ele?
Metoda TestercaneAdaptyGiveType () testeaz─â cardul „Adaptare ARCANE”. Fiecare juc─âtor prime╚Öte carduri ├«ntr-o anumit─â zon─â de joc. ╚śi datorit─â copierii, Playera a primit 2 c─âr╚Ťi „SilverCoat leu” identice ├«n loc de joac─â „cimitir”, iar PlayerBdun nu sa ├«nt├ómplat nimic. ├Än plus, un fel de magie ╚Öi ├«ncerca╚Ťi testarea.
C├ónd testul ajunge la „cimitirul” de jucator ├«n raliul curent, atunci executarea testului nu intr─â niciodat─â ├«n bucl─â, pentru c─â nu era nimic ├«n „cimitirul”. Aceasta este ceea ce am descoperit cu vechiul sistem vechi.out.println () c├ónd ├«ncepe╚Ťi testul.
Copy-Paste corectat:

....addCard(Zone.HAND, playerA, "Silvercoat Lion");addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion"); // <=addCard(Zone.HAND, playerB, "Silvercoat Lion");addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");addCard(Zone.GRAVEYARD, playerB, "Silvercoat Lion"); // <=....

După schimbarea codului, când am executat testul, căutarea creaturilor în Cimitirul Jucatorului a început să lucreze. Ave, sistem.out.println ()!
Testul este verde înainte și după corectare, care este mult noroc. Dar, în cazul modificărilor care modifică logica executării programului, un astfel de test vă va face un serviciu rău, informându-vă despre succes, chiar dacă există erori.
Același copie-stick în altă parte:

  • V6072 Au fost g─âsite dou─â fragmente de cod similare. Aceasta poate fi o eroare de tastare, iar variabila „Playerb” ar trebui utilizat─â ├«n locul „Playera”. PictersServantTest.java (33), PictersServantTest.java (27), PictersServantTest.java (31)
  • v6072 Au fost g─âsite dou─â fragmente de cod similare. Aceasta poate fi o eroare de tastare, iar variabila „Playerb” ar trebui utilizat─â ├«n locul „Playera”. SubtiphangingeffectStest.java (32), subtiphanghangeffectStest.java (28), subtiphanghangeffectstest.java (26), subtiphanghanghangeffectstest.java (30)

Avertisment N11

V6086 Cod suspectat Formatare. Cuv├óntul cheie „altceva” este probabil lips─â. Deckimporter.java (23)

public static DeckImporter getDeckImporter(String file) { if (file == null) { return null; } if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) { // <= return new DecDeckImporter(); } else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) { return new MWSDeckImporter(); } else if (file.toLowerCase(Locale.ENGLISH).endsWith("txt")) { return new TxtDeckImporter(haveSideboardSection(file)); } .... else { return null; }}

Acest extract de cod ilustrează acest lucru. În acest caz, din cauza exprimării returnării null, o inexactitate în formatare nu duce la nimic, dar este rece să găsească astfel de cazuri, deoarece nu este necesar.
Lua╚Ťi ├«n considerare un caz ├«n care omisiunea celuilalt poate duce la un comportament nea╚Öteptat:

public SomeType smtMethod(SomeType obj) { .... if (obj == null) { obj = getNewObject(); } if (obj.isSomeObject()) { // some logic } else if (obj.isOtherSomething()) { obj = calulateNewObject(obj); // some logic } .... else { // some logic } return obj;}

acum, ├«n cazul obj = null, obiectul ├«n cauz─â va fi atribuit O valoare, iar altceva lipsit─â de altceva vor determina obiectul nou alocat s─â verifice de-a lungul lan╚Ťului dac─â-altcineva, ├«n timp ce obiectul trebuia s─â se ├«ntoarc─â imediat la metoda.

Concluzie

Verificarea Xmage este un alt articol care dezv─âluie capacit─â╚Ťile analizoarelor statice moderne. ├Än dezvoltarea modern─â, nevoia lor cre╚Öte doar, deoarece complexitatea software-ului cre╚Öte. ╚śi indiferent de num─ârul de versiuni, teste, comentarii utilizatorilor: un bug va g─âsi ├«ntotdeauna o defec╚Ťiune pentru a introduce baza de cod. Deci, de ce nu ad─âuga╚Ťi o alt─â barier─â ├«n ap─ârarea dvs.?
Dup─â cum ├«n╚Ťelege╚Ťi, analizoarele sunt supuse unor false pozitive (inclusiv PVS-Studio Java). Acesta poate fi rezultatul unui defect evident ╚Öi al unui cod prea confuz (din p─âcate, analizorul nu la ├«n╚Ťeles). Trebuie s─â le trata╚Ťi cu ├«n╚Ťelegere ╚Öi s─â v─â dezabona╚Ťi imediat f─âr─â ezitare, dar ├«n timp ce fals pozitive a╚Öteapt─â corec╚Ťia lor, pute╚Ťi utiliza una din metodele de avertizare.
├Än concluzie, v─â sugerez personal s─â „atinge╚Ťi” analizorul desc─ârc├ónd-l de pe site-ul nostru.

[/ div>

Dac─â dori╚Ťi s─â ├«mp─ârt─â╚Öi╚Ťi acest articol cu un public de limb─â englez─â, v─â rug─âm s─â utiliza╚Ťi Link de traducere: Maxim Stefanov. Verificarea codului Xmage ╚Öi de ce nu ve╚Ťi putea ob╚Ťine c─âr╚Ťile rare speciale din colec╚Ťia de labirint a Dragonului.

Leave a comment

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *