Ien fan 'e meast aktuele senario's foar it brûken fan de PVS-Studio-analysator is syn yntegraasje mei CI-systemen. En hoewol't de analyze fan in PVS-Studio projekt út hast alle trochgeande yntegraasje systeem kin wurde boud yn mar in pear kommando's, wy bliuwe te meitsje dit proses noch handiger. PVS-Studio hat no stipe foar it konvertearjen fan analysatorútfier yn in formaat foar TeamCity - TeamCity Inspections Type. Litte wy sjen hoe't it wurket.
Ynformaasje oer de brûkte software
Ynformaasje oer it projekt ûnder stúdzje
Litte wy dizze funksjonaliteit besykje op in praktysk foarbyld - lit ús it OpenRCT2-projekt analysearje.
oanpassing
Om tiid te besparjen, sil ik wierskynlik it ynstallaasjeproses oerslaan en begjinne fan it momint dat ik de TeamCity-tsjinner op myn kompjûter haw. Wy moatte gean nei: localhost:{poarte oantsjutte tidens it ynstallaasjeproses} (yn myn gefal, localhost:9090) en autorisaasjegegevens ynfiere. Nei it ynfieren wurde wy begroete troch:
Klikje op de knop Project oanmeitsje. Selektearje dan Hânmjittich en folje de fjilden yn.
Nei it drukken op de knop Meitsje, wy wurde begroete troch in finster mei ynstellings.
Litte wy klikke Meitsje build konfiguraasje.
Folje de fjilden yn en klikje Meitsje. Wy sjogge in finster dat jo freget om in ferzjekontrôlesysteem te selektearjen. Om't de boarnen al lokaal lizze, klikje jo Oerslaan.
As lêste geane wy troch nei de projektynstellingen.
Litte wy montagestappen tafoegje, klikje om dit te dwaan: Boustappen -> Boustap taheakje.
Hjir kieze wy:
- Runner type -> Kommandorigel
- Run -> Oanpaste skript
Om't wy analyse sille útfiere tidens projektkompilaasje, moatte gearstalling en analyse ien stap wêze, dus folje it fjild yn Oanpaste skript:
Wy sille letter nei yndividuele stappen sjen. It is wichtich dat it laden fan de analysator, it gearstallen fan it projekt, it analysearjen, it útfieren fan it rapport en it opmeitsjen fan it mar alve rigels koade nimt.
It lêste wat wy moatte dwaan is de omjouwingsfariabelen ynstelle, dy't ik guon manieren haw sketst om har lêsberens te ferbetterjen. Om dit te dwaan, litte wy trochgean: Parameters -> Nije parameter tafoegje en foegje trije fariabelen ta:
Alles wat jo hoege te dwaan is op de knop drukke run yn 'e rjochter boppeste hoeke. Wylst it projekt wurdt gearstald en analysearre, Ik sil fertelle jo oer it skript.
Direkt skript
Earst moatte wy de lêste PVS-Studio-distribúsje downloade. Dêrfoar brûke wy de Chocolatey-pakketbehearder. Foar wa't hjir mear oer witte wol, is der in oerienkommende
choco install pvs-studio -y
Litte wy dan it CLMonitor-projekt foar it folgjen fan it trackingprogramma lansearje.
%CLmon% monitor –-attach
Dan sille wy it projekt bouwe as in omjouwingsfariabele MSB is it paad nei de ferzje fan MSBuild ik moat bouwen
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
Litte wy de oanmeld- en lisinsjekaai ynfiere foar PVS-Studio:
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
Nei it bouwen is foltôge, rinne CLMonitor opnij om foarbewurke bestannen en statyske analyse te generearjen:
%CLmon% analyze -l "c:ptest.plog"
Dan sille wy in oar nut brûke fan ús distribúsje. PlogConverter konvertearret in rapport fan in standertformaat nei in TeamCity-spesifike opmaak. Hjirmei sille wy it direkt kinne besjen yn it boufinster.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
De lêste stap is om it opmakke rapport yn te werjaan stdout, wêr't it wurdt ophelle troch de TeamCity-parser.
type "C:tempptest.plog_TeamCity.txt"
Folsleine skriptkoade:
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"
Yn 'e tuskentiid is de gearstalling en analyse fan it projekt mei súkses foltôge, kinne wy gean nei it ljepblêd Projects en meitsje der wis fan.
No litte wy op klikke Ynspeksjes Totaalom te gean nei it besjen fan it analysatorrapport:
Warskôgings wurde groepearre troch diagnostyske regelnûmers. Om troch de koade te navigearjen, moatte jo klikke op it linenûmer mei de warskôging. Klikje op it fraachteken yn 'e rjochter boppeste hoeke sil jo in nije ljepper iepenje mei dokumintaasje. Jo kinne ek navigearje troch de koade troch te klikken op it rigelnûmer mei de warskôging foar analysator. Navigaasje fan in kompjûter op ôfstân is mooglik by it brûken SourceTreeRoot marker. Elkenien dy't ynteressearre is yn dizze modus fan wurking fan 'e analyzer kin harsels fertroud meitsje mei de oerienkommende seksje
Besjoch de resultaten fan 'e analysator
No't wy klear binne mei it ynsetten en konfigurearjen fan 'e build, litte wy ris sjen nei wat nijsgjirrige warskôgings fûn yn it projekt wêr't wy nei sjogge.
Warskôging N1
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;
}
De analysator opmurken in flater dy't nei dynamysk allocating ûnthâld yn CreateObject, as in útsûndering optreedt, it ûnthâld wurdt net wiske, en in ûnthâld lek optreedt.
Warskôging N2
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),
....
};
In pear minsken oars as in statyske analysator koene dizze attentiviteitstest trochjaan. Dit copy-paste-foarbyld is krekt om dizze reden goed.
Warskôgings N3
struct RCT12SpriteBase
{
....
uint8_t flags;
....
};
struct rct1_peep : RCT12SpriteBase
{
....
uint8_t flags;
....
};
Fansels is it brûken fan in fariabele mei deselde namme yn 'e basisklasse en yn' e neisiet net altyd in flater. Erfskiptechnology sels giet der lykwols fanút dat alle fjilden fan 'e âlderklasse oanwêzich binne yn' e bernklasse. Troch fjilden mei deselde namme yn 'e erfgenamt te ferklearjen, meitsje wy betizing.
Warskôging N4
void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
if ((imageDirection / 8) && (imageDirection / 8) != 3)
{
....
}
....
}
Lit ús ris efkes neier sjen. Útdrukking imageDirection/8 sil wêze falsk as imageDirection leit yn it berik fan -7 oant 7. Twadde diel: (imageDirection / 8) != 3 kontrôles imageDirection om bûten it berik te wêzen: respektivelik fan -31 oant -24 en fan 24 oant 31. It liket my frij frjemd om nûmers te kontrolearjen foar opname yn in bepaald berik op dizze manier en, sels as d'r gjin flater is yn dit stikje koade, soe ik riede om dizze betingsten opnij te skriuwen om eksplisyt te wêzen. Dit soe it libben folle makliker meitsje foar de minsken dy't dizze koade lêze en ûnderhâlde.
Warskôging N5
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;
....
}
....
}
Dit koadefragmint waard nei alle gedachten krigen troch dekompilaasje. Dan, te beoardieljen nei de opmerking lofts, waard in diel fan 'e net-wurkende koade fuortsmiten. Der binne lykwols noch in pear operaasjes oer cursorId, dy't ek net folle sin hawwe.
Warskôging N6
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); // <=
}
....
}
Dizze koade is frij maklik te korrigearjen; jo moatte it gewoan in tredde kear kontrolearje spiler oan in nul-oanwizer, of heakje it ta oan it lichem fan 'e betingsten. Ik soe de twadde opsje foarstelle:
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);
}
}
....
}
Warskôging N7
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));
....
}
....
}
Jo kinne in hurd te lêzen rigel koade yn ien klap kwytreitsje en it probleem oplosse troch te kontrolearjen foar nullptr. Ik stel foar om de koade as folgjend te feroarjen:
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);
....
}
....
}
Warskôging N8
void CustomListView::MouseUp(....)
{
....
if (!ColumnHeaderPressedCurrentState)
{
ColumnHeaderPressed = std::nullopt;
ColumnHeaderPressedCurrentState = false;
Invalidate();
}
}
De koade sjocht der hiel nuver út. It liket my ta dat der in typflater wie yn de betingst of by it opnij tawizen fan de fariabele ColumnHeaderPressedCurrentState wearden falsk.
konklúzje
Lykas wy kinne sjen, is it yntegrearjen fan de statyske analysator PVS-Studio yn jo TeamCity-projekt frij ienfâldich. Om dit te dwaan is it genôch om mar ien lyts konfiguraasjetriem te skriuwen. Troch de koade te kontrolearjen kinne jo problemen fuortendaliks nei de gearstalling identifisearje, wat sil helpe om se te eliminearjen as de kompleksiteit en kosten fan feroaringen noch leech binne.
As jo dit artikel wolle diele mei in Ingelsktalig publyk, brûk dan de oersettingskeppeling: Vladislav Stolyarov.
Boarne: www.habr.com