PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Ein af nýjustu atburðarásunum fyrir notkun PVS-Studio greiningartækisins er samþætting þess við CI kerfi. Og þó að greining á PVS-Studio verkefni frá nánast hvaða samfelldu samþættingarkerfi sé hægt að byggja inn í örfáar skipanir, höldum við áfram að gera þetta ferli enn þægilegra. PVS-Studio hefur nú stuðning við að umbreyta úttak greiningartækis í snið fyrir TeamCity - TeamCity Inspections Type. Við skulum sjá hvernig það virkar.

Upplýsingar um hugbúnaðinn sem notaður er

PVS-stúdíó — kyrrstöðugreiningartæki fyrir C, C++, C# og Java kóða, hannað til að auðvelda það verkefni að finna og leiðrétta ýmsar tegundir villna. Hægt er að nota greiningartækið á Windows, Linux og macOS. Í þessari grein munum við virkan nota ekki aðeins greiningartækið sjálft, heldur einnig nokkur tól frá dreifingu þess.

CLMonitor — er eftirlitsþjónn sem fylgist með ræsingu þýðanda. Það verður að keyra það strax áður en byrjað er að byggja verkefnið þitt. Í snooping ham mun þjónninn stöðva keyrslur allra studdra þýðenda. Það er athyglisvert að þetta tól er aðeins hægt að nota til að greina C/C++ verkefni.

PlogConverter – tól til að umbreyta greiningarskýrslum í mismunandi snið.

Upplýsingar um verkefnið í rannsókn

Við skulum prófa þessa virkni á hagnýtu dæmi - við skulum greina OpenRCT2 verkefnið.

OpenRCT2 - opin útfærsla á leiknum RollerCoaster Tycoon 2 (RCT2), stækkar hann með nýjum aðgerðum og lagar villur. Gameplay snýst um að byggja og viðhalda skemmtigarði sem inniheldur ferðir, verslanir og aðstöðu. Spilarinn verður að reyna að græða og viðhalda góðu orðspori garðsins á meðan hann heldur gestum ánægðum. OpenRCT2 gerir þér kleift að spila bæði í atburðarás og sandkassa. Sviðsmyndir krefjast þess að leikmaðurinn ljúki tilteknu verkefni innan ákveðins tíma, en Sandbox gerir leikmanninum kleift að byggja sveigjanlegri garður án takmarkana eða fjárhags.

aðlögun

Til að spara tíma mun ég líklega sleppa uppsetningarferlinu og byrja frá því augnabliki þegar ég er með TeamCity þjóninn í gangi á tölvunni minni. Við þurfum að fara á: localhost:{port tilgreint í uppsetningarferlinu} (í ​​mínu tilfelli, localhost:9090) og slá inn heimildargögn. Eftir inngöngu taka á móti okkur:

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Smelltu á hnappinn Búa til verkefni. Næst skaltu velja Handvirkt og fylla út reitina.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Eftir að hafa ýtt á hnappinn Búa til, tekur á móti okkur gluggi með stillingum.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Við skulum smella Búðu til byggingarstillingar.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Fylltu út reitina og smelltu Búa til. Við sjáum glugga sem biður þig um að velja útgáfustýringarkerfi. Þar sem heimildirnar eru þegar staðsettar á staðnum, smelltu Fara.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Að lokum förum við yfir í verkefnastillingarnar.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Við skulum bæta við samsetningarskrefum, til að gera þetta smelltu: Byggingarskref -> Bæta við byggingarskrefum.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Hér veljum við:

  • Tegund hlaupara -> Skipanalína
  • Keyra -> Sérsniðið forskrift

Þar sem við munum framkvæma greiningu við samantekt verks ætti samsetning og greining að vera eitt skref, svo fylltu út reitinn Sérsniðið handrit:

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Við munum skoða einstök skref síðar. Það er mikilvægt að hlaða greiningartækið, setja saman verkefnið, greina það, gefa út skýrsluna og forsníða hana tekur aðeins ellefu línur af kóða.

Það síðasta sem við þurfum að gera er að stilla umhverfisbreyturnar, sem ég hef lýst nokkrum leiðum til að bæta læsileika þeirra. Til að gera þetta skulum við halda áfram: Færibreytur -> Bæta við nýrri færibreytu og bæta við þremur breytum:

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Allt sem þú þarft að gera er að ýta á hnappinn Hlaupa í efra hægra horninu. Á meðan verið er að setja saman og greina verkefnið mun ég segja þér frá handritinu.

Beint handrit

Fyrst þurfum við að hlaða niður nýjustu PVS-Studio dreifingunni. Til þess notum við Chocolatey pakkastjórann. Fyrir þá sem vilja vita meira um þetta er samsvarandi grein:

choco install pvs-studio -y

Næst skulum við ræsa CLMonitor verkefnisbyggingarbúnaðinn.

%CLmon% monitor –-attach

Síðan munum við byggja verkefnið upp sem umhverfisbreytu MSB er slóðin að útgáfunni af MSBuild sem ég þarf að smíða

%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable

Sláum inn innskráningar- og leyfislykilinn fyrir PVS-Studio:

%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%

Eftir að smíði er lokið skaltu keyra CLMonitor aftur til að búa til forunnar skrár og kyrrstöðugreiningu:

%CLmon% analyze -l "c:ptest.plog"

Þá munum við nota annað tól úr dreifingu okkar. PlogConverter breytir skýrslu úr stöðluðu sniði í TeamCity-sérstakt snið. Þökk sé þessu munum við geta skoðað það beint í byggingarglugganum.

%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"

Síðasta skrefið er að birta sniðið skýrsluna í stdout, þar sem það verður tekið upp af TeamCity þáttaranum.

type "C:tempptest.plog_TeamCity.txt"

Fullur handritskóði:

choco install pvs-studio -y
%CLmon% monitor --attach
set platform=x64
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
%CLmon% analyze -l "c:ptest.plog"
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
type "C:tempptest.plog_TeamCity.txt"

Í millitíðinni hefur samsetningu og greiningu á verkefninu verið lokið með góðum árangri, við getum farið í flipann verkefni og vertu viss um það.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Nú skulum við smella á Skoðanir Samtalstil að fara í að skoða greiningarskýrsluna:

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Viðvaranir eru flokkaðar eftir greiningarreglunúmerum. Til að fletta í gegnum kóðann þarftu að smella á línunúmerið með viðvöruninni. Með því að smella á spurningarmerkið í efra hægra horninu opnast nýr flipi með skjölum. Þú getur líka farið í gegnum kóðann með því að smella á línunúmerið með greiningarviðvöruninni. Leiðsögn frá fjartengdri tölvu er möguleg þegar hún er notuð SourceTreeRoot merki. Allir sem hafa áhuga á þessari notkunaraðferð greiningartækisins geta kynnt sér samsvarandi kafla skjöl.

Skoða niðurstöður greiningartækisins

Nú þegar við erum búin að dreifa og stilla bygginguna skulum við kíkja á nokkrar áhugaverðar viðvaranir sem finnast í verkefninu sem við erum að skoða.

Viðvörun N1

V773 [CWE-401] Undantekningunni var hent án þess að sleppa „niðurstöðu“ bendilinum. Minnisleki er mögulegur. libopenrct2 ObjectFactory.cpp 443

Object* CreateObjectFromJson(....)
{
  Object* result = nullptr;
  ....
  result = CreateObject(entry);
  ....
  if (readContext.WasError())
  {
    throw std::runtime_error("Object has errors");
  }
  ....
}

Object* CreateObject(const rct_object_entry& entry)
{
  Object* result;
  switch (entry.GetType())
  {
    case OBJECT_TYPE_RIDE:
      result = new RideObject(entry);
      break;
    case OBJECT_TYPE_SMALL_SCENERY:
      result = new SmallSceneryObject(entry);
      break;
    case OBJECT_TYPE_LARGE_SCENERY:
      result = new LargeSceneryObject(entry);
      break;
    ....
    default:
      throw std::runtime_error("Invalid object type");
  }
  return result;
}

Greiningartækið tók eftir villu sem eftir að hafa úthlutað minni á virkan hátt CreateObject, þegar undantekning á sér stað er minnið ekki hreinsað og minnisleki á sér stað.

Viðvörun N2

V501 Það eru eins undirtjáningar '(1ULL << WIDX_MONTH_BOX)' vinstra megin og hægra megin við '|' rekstraraðili. libopenrct2ui Cheats.cpp 487

static uint64_t window_cheats_page_enabled_widgets[] = 
{
  MAIN_CHEAT_ENABLED_WIDGETS |
  (1ULL << WIDX_NO_MONEY) |
  (1ULL << WIDX_ADD_SET_MONEY_GROUP) |
  (1ULL << WIDX_MONEY_SPINNER) |
  (1ULL << WIDX_MONEY_SPINNER_INCREMENT) |
  (1ULL << WIDX_MONEY_SPINNER_DECREMENT) |
  (1ULL << WIDX_ADD_MONEY) |
  (1ULL << WIDX_SET_MONEY) |
  (1ULL << WIDX_CLEAR_LOAN) |
  (1ULL << WIDX_DATE_SET) |
  (1ULL << WIDX_MONTH_BOX) |  // <=
  (1ULL << WIDX_MONTH_UP) |
  (1ULL << WIDX_MONTH_DOWN) |
  (1ULL << WIDX_YEAR_BOX) |
  (1ULL << WIDX_YEAR_UP) |
  (1ULL << WIDX_YEAR_DOWN) |
  (1ULL << WIDX_DAY_BOX) |
  (1ULL << WIDX_DAY_UP) |
  (1ULL << WIDX_DAY_DOWN) |
  (1ULL << WIDX_MONTH_BOX) |  // <=
  (1ULL << WIDX_DATE_GROUP) |
  (1ULL << WIDX_DATE_RESET),
  ....
};

Fáir aðrir en kyrrstöðugreiningartæki gætu staðist þetta athyglispróf. Þetta copy-paste dæmi er gott einmitt af þessari ástæðu.

Viðvaranir N3

V703 Það er skrítið að 'flags' reiturinn í afleiddum flokki 'RCT12BannerElement' skrifar yfir reitinn í grunnflokknum 'RCT12TileElementBase'. Athugunarlínur: RCT12.h:570, RCT12.h:259. libopenrct2 RCT12.h 570

struct RCT12SpriteBase
{
  ....
  uint8_t flags;
  ....
};
struct rct1_peep : RCT12SpriteBase
{
  ....
  uint8_t flags;
  ....
};

Auðvitað er það ekki alltaf villa að nota breytu með sama nafni í grunnflokknum og í afkvæminu. Hins vegar gerir erfðatæknin sjálf ráð fyrir því að öll svið foreldrabekksins séu til staðar í barnabekknum. Með því að lýsa yfir reitum með sama nafni í erfingjanum kynnum við rugling.

Viðvörun N4

V793 Það er skrítið að niðurstaðan í 'imageDirection / 8' yfirlýsingunni sé hluti af skilyrðinu. Kannski hefði átt að bera þessa fullyrðingu saman við eitthvað annað. libopenrct2 ObservationTower.cpp 38

void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
  if ((imageDirection / 8) && (imageDirection / 8) != 3)
  {
    ....
  }
  ....
}

Við skulum skoða nánar. Tjáning imageDirection/8 verður rangt ef imageDirection er á bilinu -7 til 7. Seinni hluti: (imageDirection / 8) != 3 ávísanir imageDirection fyrir að vera utan bilsins: frá -31 til -24 og frá 24 til 31, í sömu röð. Það finnst mér frekar skrítið að athuga tölur fyrir innlimun á ákveðnu bili á þennan hátt og jafnvel þó að það sé engin villa í þessum kóða, þá myndi ég mæla með því að endurskrifa þessi skilyrði til að vera skýrari. Þetta myndi gera lífið miklu auðveldara fyrir fólkið sem myndi lesa og viðhalda þessum kóða.

Viðvörun N5

V587 Skrýtin röð verkefna af þessu tagi: A = B; B = A;. Athugaðu línur: 1115, 1118. libopenrct2ui MouseInput.cpp 1118

void process_mouse_over(....)
{
  ....
  switch (window->widgets[widgetId].type)
  {
    case WWT_VIEWPORT:
      ebx = 0;
      edi = cursorId;                                 // <=
      // Window event WE_UNKNOWN_0E was called here,
      // but no windows actually implemented a handler and
      // it's not known what it was for
      cursorId = edi;                                 // <=
      if ((ebx & 0xFF) != 0)
      {
        set_cursor(cursorId);
        return;
      }
      break;
      ....
  }
  ....
}

Þetta kóðabrot var líklegast fengið með afsamsetningu. Síðan, miðað við athugasemdina sem skilin var eftir, var hluti af kóðanum sem ekki virkaði fjarlægður. Enn eru þó nokkrar aðgerðir eftir cursorId, sem líka meikar ekki mikið sens.

Viðvörun N6

V1004 [CWE-476] „Player“ bendillinn var notaður á óöruggan hátt eftir að hann var staðfestur gegn nullptr. Athugaðu línur: 2085, 2094. libopenrct2 Network.cpp 2094

void Network::ProcessPlayerList()
{
  ....
  auto* player = GetPlayerByID(pendingPlayer.Id);
  if (player == nullptr)
  {
    // Add new player.
    player = AddPlayer("", "");
    if (player)                                          // <=
    {
      *player = pendingPlayer;
       if (player->Flags & NETWORK_PLAYER_FLAG_ISSERVER)
       {
         _serverConnection->Player = player;
       }
    }
    newPlayers.push_back(player->Id);                    // <=
  }
  ....
}

Það er frekar auðvelt að leiðrétta þennan kóða; þú þarft bara að athuga hann í þriðja sinn leikmaður við núllbendingu, eða bættu því við meginmál skilyrtu yfirlýsingarinnar. Ég myndi mæla með seinni valkostinum:

void Network::ProcessPlayerList()
{
  ....
  auto* player = GetPlayerByID(pendingPlayer.Id);
  if (player == nullptr)
  {
    // Add new player.
    player = AddPlayer("", "");
    if (player)
    {
      *player = pendingPlayer;
      if (player->Flags & NETWORK_PLAYER_FLAG_ISSERVER)
      {
        _serverConnection->Player = player;
      }
      newPlayers.push_back(player->Id);
    }
  }
  ....
}

Viðvörun N7

V547 [CWE-570] Tjáning 'nafn == nullptr' er alltaf ósatt. libopenrct2 ServerList.cpp 102

std::optional<ServerListEntry> ServerListEntry::FromJson(...)
{
  auto name = json_object_get(server, "name");
  .....
  if (name == nullptr || version == nullptr)
  {
    ....
  }
  else
  {
    ....
    entry.name = (name == nullptr ? "" : json_string_value(name));
    ....
  }
  ....
}

Þú getur losað þig við erfiða kóðalínu í einni svipan og leyst vandamálið með því að athuga nullptr. Ég legg til að breyta kóðanum sem hér segir:

std::optional<ServerListEntry> ServerListEntry::FromJson(...)
{
  auto name = json_object_get(server, "name");
  .....
  if (name == nullptr || version == nullptr)
  {
    name = ""
    ....
  }
  else
  {
    ....
    entry.name = json_string_value(name);
    ....
  }
  ....
}

Viðvörun N8

V1048 [CWE-1164] 'ColumnHeaderPressedCurrentState' breytunni var úthlutað sama gildi. libopenrct2ui CustomListView.cpp 510

void CustomListView::MouseUp(....)
{
  ....
  if (!ColumnHeaderPressedCurrentState)
  {
    ColumnHeaderPressed = std::nullopt;
    ColumnHeaderPressedCurrentState = false;
    Invalidate();
  }
}

Kóðinn lítur frekar undarlega út. Mér sýnist að það hafi verið innsláttarvilla annaðhvort í ástandinu eða þegar breytan var endurúthlutað ColumnHeaderPressedCurrentState merkingar rangar.

Output

Eins og við sjáum er það frekar einfalt að samþætta PVS-Studio kyrrstöðugreiningartækið í TeamCity verkefnið þitt. Til að gera þetta er nóg að skrifa eina litla stillingarskrá. Að athuga kóðann gerir þér kleift að bera kennsl á vandamál strax eftir samsetningu, sem mun hjálpa til við að útrýma þeim þegar flókið og kostnaður við breytingar er enn lítill.

PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu
Ef þú vilt deila þessari grein með enskumælandi áhorfendum, vinsamlegast notaðu þýðingartengilinn: Vladislav Stolyarov. PVS-Stúdíó og stöðug samþætting: TeamCity. Greining á Open RollerCoaster Tycoon 2 verkefninu.

Heimild: www.habr.com

Bæta við athugasemd