Usa sa pinakabag-o nga mga senaryo sa paggamit sa PVS-Studio analyzer mao ang pag-integrate niini sa mga sistema sa CI. Ug bisan kung ang pag-analisar sa usa ka proyekto sa PVS-Studio gikan sa hapit bisan unsang padayon nga sistema sa panagsama mahimong matukod sa pipila ra nga mga mando, padayon namon nga gihimo kini nga proseso nga labi ka dali. Ang PVS-Studio karon adunay suporta alang sa pag-convert sa analisador nga output ngadto sa format para sa TeamCity - TeamCity Inspections Type. Atong tan-awon kon sa unsang paagi kini molihok.
Impormasyon bahin sa software nga gigamit
Impormasyon bahin sa proyekto nga gitun-an
Atong sulayan kini nga gamit sa usa ka praktikal nga pananglitan - atong analisahon ang proyekto sa OpenRCT2.
kausaban
Aron makadaginot sa oras, lagmit laktawan nako ang proseso sa pag-install ug magsugod gikan sa higayon nga ako adunay server sa TeamCity nga nagdagan sa akong kompyuter. Kinahanglan nga moadto kami sa: localhost: {port nga gitakda sa panahon sa proseso sa pag-install} (sa akong kaso, localhost: 9090) ug pagsulod sa datos sa pagtugot. Human sa pagsulod kita gitimbaya ni:
Pag-klik sa button sa Paghimo Project. Sunod, pilia ang Manwal ug pun-a ang mga uma.
Human sa pagpindot sa buton Paghimo, giabiabi kami sa usa ka bintana nga adunay mga setting.
Atong i-klik Paghimo pagtukod configuration.
Pun-a ang mga uma ug i-klik Paghimo. Nakita namon ang usa ka bintana nga naghangyo kanimo sa pagpili sa usa ka sistema sa pagkontrol sa bersyon. Tungod kay ang mga tinubdan nahimutang na sa lokal, i-klik Laktaw.
Sa katapusan, nagpadayon kami sa mga setting sa proyekto.
Atong idugang ang mga lakang sa asembliya, aron mahimo kini nga pag-klik: Pagtukod mga lakang -> Pagdugang lakang sa pagtukod.
Dinhi atong pilion:
- Runner type -> Command Line
- Pagdagan -> Custom nga Script
Tungod kay maghimo kami ug pagtuki sa panahon sa paghugpong sa proyekto, ang asembliya ug pagtuki kinahanglan usa ka lakang, busa pun-a ang uma Custom Script:
Atong tan-awon ang tagsa-tagsa nga mga lakang sa ulahi. Importante nga ang pagkarga sa analisador, pag-assemble sa proyekto, pag-analisar niini, pag-output sa report ug pag-format niini nagkinahanglan lamang ug onse ka linya sa code.
Ang katapusan nga butang nga kinahanglan natong buhaton mao ang pagbutang sa mga variable sa palibot, nga akong gilatid ang pipila ka mga paagi aron mapauswag ang ilang pagkabasa. Aron mahimo kini, magpadayon kita: Mga Parameter -> Pagdugang bag-ong parameter ug idugang ang tulo ka mga variable:
Ang kinahanglan nimong buhaton mao ang pagpindot sa buton run sa ibabaw nga tuo nga suok. Samtang ang proyekto gitigum ug gisusi, isulti ko kanimo ang bahin sa script.
Direkta nga script
Una, kinahanglan natong i-download ang pinakabag-o nga pag-apod-apod sa PVS-Studio. Alang niini among gigamit ang Chocolatey package manager. Para sa mga gusto makahibalo ug dugang bahin niini, adunay katugbang
choco install pvs-studio -y
Sunod, atong ilunsad ang CLMonitor project build tracking utility.
%CLmon% monitor β-attach
Dayon atong tukoron ang proyekto isip usa ka variable sa palibot MSB mao ang dalan sa bersyon sa MSBuild nga kinahanglan nakong tukuron
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
Atong isulod ang login ug license key para sa PVS-Studio:
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
Human makompleto ang pagtukod, padagana pag-usab ang CLMonitor aron makamugna og preprocessed files ug static analysis:
%CLmon% analyze -l "c:ptest.plog"
Unya mugamit mi ug laing utility gikan sa among distribution. Ang PlogConverter nag-convert sa usa ka report gikan sa usa ka standard nga format ngadto sa usa ka TeamCity-specific nga format. Salamat niini, mahimo namong tan-awon kini direkta sa bintana sa pagtukod.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
Ang katapusang lakang mao ang pagpakita sa giporma nga report sa stdout, diin kini kuhaon sa TeamCity parser.
type "C:tempptest.plog_TeamCity.txt"
Bug-os nga script code:
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"
Sa kasamtangan, ang asembliya ug pag-analisar sa proyekto malampuson nga nahuman, makaadto kami sa tab mga proyekto ug siguroha kini.
Karon atong i-klik sa Total nga Inspeksyonaron moadto sa pagtan-aw sa report sa analisador:
Ang mga pasidaan gi-grupo sa mga numero sa lagda sa diagnostic. Aron maka-navigate sa code, kinahanglan nimo nga i-klik ang numero sa linya nga adunay pasidaan. Ang pag-klik sa marka sa pangutana sa taas nga tuo nga suok magbukas kanimo usa ka bag-ong tab nga adunay dokumentasyon. Mahimo ka usab nga mag-navigate sa code pinaagi sa pag-klik sa numero sa linya nga adunay pasidaan sa analisador. Ang pag-navigate gikan sa usa ka hilit nga kompyuter posible kung gamiton SourceTreeRoot marker. Bisan kinsa nga interesado sa kini nga paagi sa operasyon sa analisador mahimong pamilyar sa katugbang nga seksyon
Pagtan-aw sa mga resulta sa analisador
Karon nga nahuman na kita sa pag-deploy ug pag-configure sa pagtukod, atong tan-awon ang pipila ka makapaikag nga mga pasidaan nga makita sa proyekto nga atong gitan-aw.
Pasidaan 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;
}
Namatikdan sa analisador ang usa ka sayup nga pagkahuman sa dinamikong paggahin sa memorya sa CreateObject, kung adunay mahitabo nga eksepsiyon, ang memorya dili ma-clear, ug ang usa ka memory leak mahitabo.
Pasidaan 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),
....
};
Pipila ka mga tawo gawas sa usa ka static analyzer ang makapasar sa kini nga pagsulay sa pagkaatentibo. Kini nga pananglitan sa pagkopya-paste maayo alang niini nga hinungdan.
Mga Pasidaan N3
struct RCT12SpriteBase
{
....
uint8_t flags;
....
};
struct rct1_peep : RCT12SpriteBase
{
....
uint8_t flags;
....
};
Siyempre, ang paggamit sa usa ka variable nga adunay parehas nga ngalan sa base nga klase ug sa kaliwat dili kanunay usa ka sayup. Bisan pa, ang teknolohiya sa kabilin mismo nagtuo nga ang tanan nga mga natad sa klase sa ginikanan naa sa klase sa bata. Pinaagi sa pagpahayag sa mga uma nga adunay parehas nga ngalan sa manununod, gipaila namon ang kalibog.
Pasidaan N4
void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
if ((imageDirection / 8) && (imageDirection / 8) != 3)
{
....
}
....
}
Atong tan-awon pag-ayo. Pagpahayag hulagwayDireksiyon/8 mahimong bakak kon Direksyon sa imahe anaa sa han-ay gikan sa -7 ngadto sa 7. Ikaduhang bahin: (Direksiyon sa hulagway / 8) != 3 mga tseke Direksyon sa imahe kay naa sa gawas sa range: gikan sa -31 hangtod -24 ug gikan sa 24 hangtod 31, matag usa. Morag katingad-an alang kanako ang pagsusi sa mga numero alang sa paglakip sa usa ka piho nga sakup sa kini nga paagi ug, bisan kung walaβy sayup sa kini nga piraso sa code, irekomenda ko nga isulat pag-usab kini nga mga kondisyon aron mahimong labi ka klaro. Kini makahimo sa kinabuhi nga mas sayon ββalang sa mga tawo nga mobasa ug magpadayon niini nga code.
Pasidaan 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;
....
}
....
}
Kini nga tipik sa code lagmit nakuha pinaagi sa pag-decompilation. Unya, sa paghukom sa komento nga nahabilin, ang bahin sa non-working code gikuha. Bisan pa, adunay nahabilin nga duha nga mga operasyon cursorId, nga dili usab kaayo masabtan.
Pasidaan 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); // <=
}
....
}
Kini nga code sayon ββββra nga matul-id; kinahanglan nimo nga susihon kini sa ikatulo nga higayon player sa usa ka null pointer, o idugang kini sa lawas sa conditional statement. Isugyot nako ang ikaduha nga kapilian:
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);
}
}
....
}
Pasidaan 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));
....
}
....
}
Mahimo nimong tangtangon ang usa ka lisud basahon nga linya sa code sa usa ka pagdagan ug sulbaron ang problema sa pagsusi sa nullptr. Gisugyot ko nga usbon ang code sama sa mosunod:
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);
....
}
....
}
Pasidaan N8
void CustomListView::MouseUp(....)
{
....
if (!ColumnHeaderPressedCurrentState)
{
ColumnHeaderPressed = std::nullopt;
ColumnHeaderPressedCurrentState = false;
Invalidate();
}
}
Ang kodigo morag katingad-an. Para nako adunay typo sa kondisyon o kung gi-assign pag-usab ang variable ColumnHeaderPressedCurrentState mga mithi bakak nga mga.
konklusyon
Sama sa among nakita, ang pag-integrate sa PVS-Studio static analyzer sa imong proyekto sa TeamCity yano ra. Aron mahimo kini, igo na ang pagsulat sa usa ka gamay nga file sa pag-configure. Ang pagsusi sa code magtugot kanimo sa pag-ila sa mga problema diha-diha dayon pagkahuman sa asembliya, nga makatabang sa pagwagtang niini kung ang pagkakomplikado ug gasto sa mga pagbag-o gamay pa.
Kung gusto nimong ipaambit kini nga artikulo sa usa ka tigpaminaw nga nagsultig English, palihug gamita ang link sa paghubad: Vladislav Stolyarov.
Source: www.habr.com