Un o'r senarios mwyaf cyfredol ar gyfer defnyddio'r dadansoddwr PVS-Studio yw ei integreiddio Γ’ systemau CI. Ac er y gellir ymgorffori dadansoddiad o brosiect PVS-Studio o bron unrhyw system integreiddio barhaus i ychydig o orchmynion, rydym yn parhau i wneud y broses hon hyd yn oed yn fwy cyfleus. Bellach mae gan PVS-Studio gefnogaeth ar gyfer trosi allbwn dadansoddwr yn fformat ar gyfer TeamCity - Math o Arolygiadau TeamCity. Gawn ni weld sut mae'n gweithio.
Gwybodaeth am y meddalwedd a ddefnyddir
Gwybodaeth am y prosiect sy'n cael ei astudio
Gadewch i ni roi cynnig ar y swyddogaeth hon gydag enghraifft ymarferol - gadewch i ni ddadansoddi'r prosiect OpenRCT2.
addasiad
Er mwyn arbed amser, mae'n debyg y byddaf yn hepgor y broses osod ac yn cychwyn o'r eiliad pan fydd gweinydd TeamCity yn rhedeg ar fy nghyfrifiadur. Mae angen i ni fynd i: localhost: {porth a nodir yn ystod y broses osod} (yn fy achos i, localhost: 9090) a mewnbynnu data awdurdodi. Ar Γ΄l dod i mewn byddwn yn cael ein cyfarch gan:
Cliciwch ar y botwm Creu Prosiect. Nesaf, dewiswch Γ’ llaw a llenwch y meysydd.
Ar Γ΄l pwyso'r botwm Creu, cawn ein cyfarch gan ffenestr gyda gosodiadau.
Gadewch i ni glicio Creu cyfluniad adeiladu.
Llenwch y meysydd a chliciwch Creu. Rydym yn gweld ffenestr yn gofyn i chi ddewis system rheoli fersiwn. Gan fod y ffynonellau eisoes wedi'u lleoli'n lleol, cliciwch Skip.
Yn olaf, symudwn ymlaen i osodiadau'r prosiect.
Gadewch i ni ychwanegu camau cynulliad, i wneud hyn cliciwch: Adeiladu camau -> Ychwanegu cam adeiladu.
Yma rydym yn dewis:
- Math rhedwr -> Llinell Reoli
- Rhedeg -> Sgript Custom
Gan y byddwn yn perfformio dadansoddiad yn ystod llunio prosiect, dylai cydosod a dadansoddi fod yn un cam, felly llenwch y maes Sgript Custom:
Byddwn yn edrych ar gamau unigol yn ddiweddarach. Mae'n bwysig bod llwytho'r dadansoddwr, cydosod y prosiect, ei ddadansoddi, allbynnu'r adroddiad a'i fformatio yn cymryd dim ond un ar ddeg llinell o god.
Y peth olaf y mae angen inni ei wneud yw gosod y newidynnau amgylchedd, yr wyf wedi amlinellu rhai ffyrdd o wella eu darllenadwyedd. I wneud hyn, gadewch i ni symud ymlaen: Paramedrau -> Ychwanegu paramedr newydd ac ychwanegu tri newidyn:
Y cyfan sy'n rhaid i chi ei wneud yw pwyso'r botwm Run yn y gornel dde uchaf. Tra bod y prosiect yn cael ei gydosod a'i ddadansoddi, byddaf yn dweud wrthych am y sgript.
Sgript yn uniongyrchol
Yn gyntaf, mae angen inni lawrlwytho'r dosbarthiad PVS-Studio diweddaraf. Ar gyfer hyn rydym yn defnyddio'r rheolwr pecyn Chocolatey. I'r rhai sydd am wybod mwy am hyn, mae cyfatebol
choco install pvs-studio -y
Nesaf, gadewch i ni lansio cyfleustodau olrhain adeiladu prosiect CLMonitor.
%CLmon% monitor β-attach
Yna byddwn yn adeiladu'r prosiect fel newidyn amgylcheddol MSB yw'r llwybr i'r fersiwn o MBuild y mae angen i mi ei adeiladu
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
Gadewch i ni nodi'r allwedd mewngofnodi a thrwydded ar gyfer PVS-Studio:
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
Ar Γ΄l i'r gwaith adeiladu gael ei gwblhau, rhedwch CLMonitor eto i gynhyrchu ffeiliau wedi'u prosesu ymlaen llaw a dadansoddiad statig:
%CLmon% analyze -l "c:ptest.plog"
Yna byddwn yn defnyddio cyfleustodau arall o'n dosbarthiad. Mae PlogConverter yn trosi adroddiad o fformat safonol i fformat sy'n benodol i TeamCity. Diolch i hyn, byddwn yn gallu ei weld yn uniongyrchol yn y ffenestr adeiladu.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
Y cam olaf yw dangos yr adroddiad wedi'i fformatio i mewn stdout, lle bydd y parser TeamCity yn ei godi.
type "C:tempptest.plog_TeamCity.txt"
Cod sgript llawn:
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 y cyfamser, mae cynulliad a dadansoddiad y prosiect wedi'i gwblhau'n llwyddiannus, gallwn fynd i'r tab prosiectau a gwnewch yn siwr ohono.
Nawr gadewch i ni glicio ar Cyfanswm yr Arolygiadaui fynd i weld adroddiad y dadansoddwr:
Mae rhybuddion yn cael eu grwpio yn Γ΄l rhifau rheolau diagnostig. I lywio drwy'r cod, mae angen i chi glicio ar y rhif llinell gyda'r rhybudd. Bydd clicio ar y marc cwestiwn yn y gornel dde uchaf yn agor tab newydd i chi gyda dogfennaeth. Gallwch hefyd lywio trwy'r cod trwy glicio ar y rhif llinell gyda rhybudd y dadansoddwr. Mae llywio o gyfrifiadur o bell yn bosibl wrth ddefnyddio FfynhonnellTreeRoot marciwr. Gall unrhyw un sydd Γ’ diddordeb yn y dull hwn o weithredu'r dadansoddwr ymgyfarwyddo Γ’'r adran gyfatebol
Gweld canlyniadau'r dadansoddwr
Nawr ein bod ni wedi gorffen lleoli a ffurfweddu'r adeilad, gadewch i ni edrych ar rai rhybuddion diddorol a ddarganfuwyd yn y prosiect rydyn ni'n edrych arno.
Rhybudd 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;
}
Sylwodd y dadansoddwr wall ar Γ΄l dyrannu cof yn ddeinamig i mewn Creu Gwrthrych, pan fydd eithriad yn digwydd, nid yw'r cof yn cael ei glirio, ac mae gollyngiad cof yn digwydd.
Rhybudd 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),
....
};
Ychydig iawn o bobl heblaw dadansoddwr statig a allai basio'r prawf sylw hwn. Mae'r enghraifft copi-gludo hon yn dda am yr union reswm hwn.
Rhybuddion N3
struct RCT12SpriteBase
{
....
uint8_t flags;
....
};
struct rct1_peep : RCT12SpriteBase
{
....
uint8_t flags;
....
};
Wrth gwrs, nid yw defnyddio newidyn gyda'r un enw yn y dosbarth sylfaenol ac yn y disgynnydd bob amser yn gamgymeriad. Fodd bynnag, mae technoleg etifeddiaeth ei hun yn rhagdybio bod holl feysydd y dosbarth rhiant yn bresennol yn y dosbarth plentyn. Trwy ddatgan caeau gyda'r un enw yn yr etifedd, rydym yn creu dryswch.
Rhybudd N4
void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
if ((imageDirection / 8) && (imageDirection / 8) != 3)
{
....
}
....
}
Gadewch i ni edrych yn agosach. Mynegiant delweddCyfarwyddyd/8 bydd yn anwir os delweddCyfeiriad yn yr ystod o -7 i 7. Ail ran: (imageDirection/8) !=3 gwiriadau delweddCyfeiriad am fod y tu allan i'r ystod: o -31 i -24 ac o 24 i 31, yn y drefn honno. Mae'n ymddangos yn eithaf rhyfedd i mi wirio niferoedd i'w cynnwys mewn ystod benodol yn y modd hwn a, hyd yn oed os nad oes gwall yn y darn hwn o god, byddwn yn argymell ailysgrifennu'r amodau hyn i fod yn fwy eglur. Byddai hyn yn gwneud bywyd yn llawer haws i'r bobl a fyddai'n darllen ac yn cynnal y cod hwn.
Rhybudd 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;
....
}
....
}
Mae'n debyg mai trwy ddadgrynhoi y cafwyd y darn cod hwn. Yna, a barnu yn Γ΄l y sylw a adawyd, tynnwyd rhan o'r cod nad oedd yn gweithio. Fodd bynnag, mae cwpl o lawdriniaethau ar Γ΄l o hyd cyrsorId, sydd hefyd ddim yn gwneud llawer o synnwyr.
Rhybudd 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); // <=
}
....
}
Mae'r cod hwn yn eithaf hawdd i'w gywiro; does ond angen i chi ei wirio am y trydydd tro chwaraewr i bwyntydd null, neu ei ychwanegu at gorff y datganiad amodol. Byddwn yn awgrymu'r ail opsiwn:
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);
}
}
....
}
Rhybudd 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));
....
}
....
}
Gallwch gael gwared ar linell o god anodd ei darllen mewn un swoop syrthio a datrys y broblem gyda gwirio am nullptr. Awgrymaf newid y cod fel a ganlyn:
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);
....
}
....
}
Rhybudd N8
void CustomListView::MouseUp(....)
{
....
if (!ColumnHeaderPressedCurrentState)
{
ColumnHeaderPressed = std::nullopt;
ColumnHeaderPressedCurrentState = false;
Invalidate();
}
}
Mae'r cod yn edrych yn eithaf rhyfedd. Mae'n ymddangos i mi fod yna deip naill ai yn y cyflwr neu wrth ail-neilltuo'r newidyn ColumnHeaderPressedCurrentState ystyron ffug.
Allbwn
Fel y gallwn weld, mae integreiddio'r dadansoddwr statig PVS-Studio i'ch prosiect TeamCity yn eithaf syml. I wneud hyn, mae'n ddigon ysgrifennu un ffeil ffurfweddu fach yn unig. Bydd gwirio'r cod yn caniatΓ‘u ichi nodi problemau yn syth ar Γ΄l y cynulliad, a fydd yn helpu i gael gwared arnynt pan fydd cymhlethdod a chost newidiadau yn dal yn isel.
Os ydych chi am rannu'r erthygl hon Γ’ chynulleidfa Saesneg ei hiaith, defnyddiwch y ddolen gyfieithu: Vladislav Stolyarov.
Ffynhonnell: hab.com