Salah sawijining skenario paling anyar kanggo nggunakake analisa PVS-Studio yaiku integrasi karo sistem CI. Lan sanajan analisa proyek PVS-Studio saka meh kabeh sistem integrasi terus-terusan bisa dibangun mung sawetara printah, kita terus nggawe proses iki luwih trep. PVS-Studio saiki duwe dhukungan kanggo ngowahi output analisa dadi format kanggo TeamCity - TeamCity Inspections Type. Ayo ndeleng cara kerjane.
Informasi babagan piranti lunak sing digunakake
Informasi babagan proyek sing diteliti
Coba fungsi iki kanthi conto praktis - ayo nganalisa proyek OpenRCT2.
imbuhan
Kanggo ngirit wektu, aku mbokmenawa bakal ngliwati proses instalasi lan miwiti saka wayahe nalika server TeamCity mlaku ing komputer. Kita kudu pindhah menyang: localhost: {port sing ditemtokake sajrone proses instalasi} (ing kasusku, localhost: 9090) lan ketik data wewenang. Sawise mlebu kita bakal disambut dening:
Klik tombol Nggawe Proyek. Sabanjure, pilih Manual lan isi kolom.
Sawise mencet tombol nggawe, kita disambut dening jendhela karo setelan.
Ayo klik Nggawe konfigurasi mbangun.
Isi kolom lan klik nggawe. Kita ndeleng jendhela sing njaluk sampeyan milih sistem kontrol versi. Wiwit sumber wis ana ing lokal, klik Skip.
Pungkasan, kita pindhah menyang setelan proyek.
Ayo nambah langkah-langkah perakitan, kanggo nindakake iki klik: Mbangun langkah -> Tambah langkah mbangun.
Kene kita milih:
- Tipe Runner -> Command Line
- Run -> Custom Script
Awit kita bakal nindakake analisis sajrone kompilasi proyek, perakitan lan analisis kudu dadi siji langkah, mula isi lapangan Skrip Khusus:
Kita bakal nliti langkah-langkah individu mengko. Penting loading analyzer, ngumpulake proyek, nganalisa, output laporan lan format mung mbutuhake sewelas baris kode.
Babagan pungkasan sing kudu ditindakake yaiku nyetel variabel lingkungan, sing aku wis mbatesi sawetara cara kanggo nambah keterbacaan. Kanggo nindakake iki, ayo nerusake: Parameter -> Tambah parameter anyar lan nambah telung variabel:
Sampeyan mung kudu mencet tombol Run ing pojok tengen ndhuwur. Nalika proyek kasebut dirakit lan dianalisis, aku bakal ngandhani babagan naskah kasebut.
Langsung skrip
Pisanan, kita kudu ngundhuh distribusi PVS-Studio paling anyar. Kanggo iki, kita nggunakake manajer paket Chocolatey. Kanggo sing pengin ngerti luwih lengkap babagan iki, ana sing cocog
choco install pvs-studio -y
Sabanjure, ayo miwiti utilitas pelacakan proyek CLMonitor.
%CLmon% monitor β-attach
Banjur kita bakal mbangun proyek kasebut minangka variabel lingkungan MSB iku path kanggo versi MSBuild aku kudu mbangun
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
Ayo ketik login lan kunci lisensi kanggo PVS-Studio:
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
Sawise mbangun rampung, bukak CLmonitor maneh kanggo ngasilake file sing wis diproses lan analisis statis:
%CLmon% analyze -l "c:ptest.plog"
Banjur kita bakal nggunakake sarana liyane saka distribusi kita. PlogConverter ngowahi laporan saka format standar menyang format khusus TeamCity. Thanks kanggo iki, kita bakal bisa ndeleng langsung ing jendhela mbangun.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
Langkah pungkasan yaiku nampilake laporan format ing stdout, ngendi iku bakal dijupuk dening TeamCity parser.
type "C:tempptest.plog_TeamCity.txt"
Kode skrip lengkap:
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"
Ing sawetoro wektu, perakitan lan analisis proyek wis rampung kanthi sukses, kita bisa pindhah menyang tab projects lan priksa manawa.
Saiki ayo klik Inspeksi Totalkanggo pindhah menyang ndeleng laporan analyzer:
Bebaya diklompokakΓ© miturut nomer aturan diagnostik. Kanggo navigasi liwat kode, sampeyan kudu ngeklik ing nomer baris karo bebaya. Ngeklik tandha pitakon ing pojok sisih ndhuwur bakal mbukak tab anyar kanthi dokumentasi. Sampeyan uga bisa navigasi liwat kode kanthi ngeklik ing nomer baris karo bebaya analyzer. Navigasi saka komputer remot bisa nalika nggunakake SourceTreeRoot panandha. Sapa wae sing kasengsem ing mode operasi penganalisa iki bisa kenal karo bagean sing cocog
Ndeleng asil analyzer
Saiki kita wis rampung deploying lan configuring mbangun, ayo kang njupuk dipikir ing sawetara bebaya menarik ditemokakΓ© ing project kita lagi looking ing.
Warning 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;
}
Analisa weruh kesalahan sing sawise mbosenke allocating memori ing CreateObject, nalika ana pangecualian, memori ora dibusak, lan ana bocor memori.
Warning 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),
....
};
Sawetara wong saliyane analisa statis bisa lulus tes perhatian iki. Conto copy-paste iki apik kanggo alesan iki.
Warning N3
struct RCT12SpriteBase
{
....
uint8_t flags;
....
};
struct rct1_peep : RCT12SpriteBase
{
....
uint8_t flags;
....
};
Mesthi, nggunakake variabel kanthi jeneng sing padha ing kelas dhasar lan ing turunan ora tansah kesalahan. Nanging, teknologi warisan dhewe nganggep yen kabeh lapangan kelas induk ana ing kelas anak. Kanthi nyatakake lapangan kanthi jeneng sing padha ing ahli waris, kita ngenalake kebingungan.
Warning N4
void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
if ((imageDirection / 8) && (imageDirection / 8) != 3)
{
....
}
....
}
Ayo dideleng kanthi cetha. Ekspresi gambarArah/8 bakal palsu yen gambarArah ana ing kisaran saka -7 nganti 7. Bagian kapindho: (gambarArah / 8) != 3 mriksa gambarArah kanggo njaba sawetara: saka -31 kanggo -24 lan saka 24 kanggo 31, mungguh. Iku misale jek cukup aneh kanggo kula mriksa nomer kanggo Gawan ing sawetara tartamtu ing cara iki lan, sanajan ora ana kesalahan ing Piece saka kode, Aku nyaranake rewriting kahanan iki dadi luwih eksplisit. Iki bakal nggawe urip luwih gampang kanggo wong sing maca lan njaga kode iki.
Warning 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;
....
}
....
}
Fragmen kode iki paling mungkin dipikolehi kanthi dekompilasi. Banjur, miturut komentar sing ditinggalake, bagean saka kode sing ora bisa digunakake wis dibusak. Nanging, isih ana sawetara operasi sing isih ana kursorId, kang uga ora nggawe akeh pangertèn.
Warning 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); // <=
}
....
}
Kode iki gampang dibenerake; sampeyan mung kudu mriksa kaping telune pamuter menyang null pointer, utawa nambah menyang awak statement kondisional. Aku bakal menehi saran pilihan kapindho:
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);
}
}
....
}
Warning 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));
....
}
....
}
Sampeyan bisa ngilangi baris kode sing angel diwaca kanthi cepet lan ngrampungake masalah kanthi mriksa nullptr. Aku saranake ngganti kode kaya ing ngisor iki:
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);
....
}
....
}
Warning N8
void CustomListView::MouseUp(....)
{
....
if (!ColumnHeaderPressedCurrentState)
{
ColumnHeaderPressed = std::nullopt;
ColumnHeaderPressedCurrentState = false;
Invalidate();
}
}
Kode katon cukup aneh. Iku misale jek kula sing ana salah ketik salah siji ing kondisi utawa nalika maneh nemtokake variabel ColumnHeaderPressedCurrentState angka palsu.
kesimpulan
Kaya sing kita deleng, nggabungake analisa statis PVS-Studio menyang proyek TeamCity sampeyan cukup gampang. Kanggo nindakake iki, cukup nulis mung siji file konfigurasi cilik. Priksa kode bakal ngidini sampeyan ngenali masalah sanalika sawise perakitan, sing bakal mbantu ngilangi nalika kerumitan lan biaya owah-owahan isih sithik.
Yen sampeyan pengin nuduhake artikel iki karo pamirsa sing nganggo basa Inggris, gunakake tautan terjemahan: Vladislav Stolyarov.
Source: www.habr.com