Salah sahiji skenario anu paling ayeuna pikeun ngagunakeun analisa PVS-Studio nyaéta integrasina sareng sistem CI. Sarta sanajan analisa hiji proyék PVS-Studio tina ampir sagala sistem integrasi kontinyu bisa diwangun kana ngan sababaraha Paréntah, urang neruskeun prosés ieu malah leuwih merenah. PVS-Studio ayeuna gaduh dukungan pikeun ngarobih kaluaran analisa kana format pikeun TeamCity - TeamCity Inspections Type. Hayu urang tingali kumaha gawéna.
Émbaran ngeunaan software dipaké
Inpormasi ngeunaan proyék anu ditalungtik
Hayu urang coba fungsionalitas ieu dina conto praktis - hayu urang nganalisis proyék OpenRCT2.
carana ngatur
Dina raraga ngahemat waktos, abdi sigana bakal skip prosés instalasi tur mimitian ti momen nalika kuring boga server TeamCity jalan dina komputer kuring. Urang kudu indit ka: localhost: {port husus salila prosés instalasi} (bisi kuring, localhost: 9090) jeung asupkeun data otorisasina. Saatos lebet urang bakal disambut ku:
Pencét kana tombol Jieun Proyék. Teras, pilih Sacara manual sareng eusian sawah.
Sanggeus mencet tombol nyiptakeun, urang disambut ku jandela kalawan setelan.
Hayu urang klik Jieun konfigurasi ngawangun.
Eusian widang teras klik nyiptakeun. Kami ningali jandela naroskeun anjeun milih sistem kontrol versi. Kusabab sumberna parantos aya sacara lokal, klik ngaliwatan.
Tungtungna, urang ngaléngkah ka setélan proyék.
Hayu urang tambahkeun léngkah assembly, pikeun ngalakukeun ieu klik: Léngkah ngawangun -> Tambahkeun léngkah ngawangun.
Di dieu urang milih:
- Tipe runner -> Jalur Komando
- Jalankeun -> Custom Script
Kusabab urang bakal ngalakukeun analisis salila kompilasi proyék, assembly jeung analisis kedah hiji hambalan, jadi eusian lapangan Script custom:
Urang bakal ningali léngkah individu engké. Kadé loading analyzer, assembling proyék, analisa eta, outputting laporan jeung pormat nu diperlukeun ngan sabelas garis kode.
Hal anu terakhir anu kedah urang laksanakeun nyaéta nyetél variabel lingkungan, anu ku kuring parantos digariskeun sababaraha cara pikeun ningkatkeun kabacana. Jang ngalampahkeun ieu, hayu urang ngaléngkah: Parameter -> Tambahkeun parameter anyar sareng tambahkeun tilu variabel:
Sadaya anu anjeun kedah laksanakeun nyaéta pencét tombol lalumpatan di pojok katuhu luhur. Nalika proyékna dirakit sareng dianalisis, kuring bakal nyarioskeun ka anjeun ngeunaan naskah.
Langsung naskah
Kahiji, urang kudu ngundeur PVS-Studio distribution panganyarna. Pikeun ieu kami nganggo manajer pakét Chocolatey. Pikeun anu hoyong terang langkung seueur ngeunaan ieu, aya anu saluyu
choco install pvs-studio -y
Salajengna, hayu urang ngaluncurkeun utilitas pelacak ngawangun proyék CLMonitor.
%CLmon% monitor –-attach
Teras we bakal ngawangun proyék salaku variabel lingkungan MSB nyaeta jalur ka versi MSBuild Abdi peryogi ngawangun
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
Hayu urang lebetkeun login sareng konci lisénsi pikeun PVS-Studio:
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
Saatos ngawangun réngsé, jalankeun CLMonitor deui pikeun ngahasilkeun file anu tos diprosés sareng analisa statik:
%CLmon% analyze -l "c:ptest.plog"
Teras kami bakal nganggo utilitas anu sanés tina distribusi kami. PlogConverter ngarobih laporan tina format standar kana format khusus TeamCity. Hatur nuhun kana ieu, urang bakal tiasa ningali éta langsung dina jandela ngawangun.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
Léngkah terakhir nyaéta ningalikeun laporan anu diformat dina stdout, dimana éta bakal dijemput ku parser TeamCity.
type "C:tempptest.plog_TeamCity.txt"
Kode naskah lengkep:
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"
Samentara éta, assembly jeung analisis proyék geus réngsé hasil, urang tiasa buka tab proyék jeung pastikeun eta.
Ayeuna hayu urang klik dina Inspections Totalpikeun ningali laporan analisa:
Warnings dikelompokeun ku angka aturan diagnostik. Pikeun napigasi ngaliwatan kode, Anjeun kudu klik dina nomer garis kalawan peringatan. Ngaklik tanda tanya di pojok katuhu luhur bakal muka anjeun tab anyar sareng dokuméntasi. Anjeun oge bisa napigasi ngaliwatan kode ku ngaklik dina nomer garis kalawan warning analyzer. Napigasi tina komputer jauh tiasa nalika nganggo SourceTreeRoot pananda. Saha waé anu kabetot dina modeu operasi analyzer ieu tiasa familiarize diri sareng bagian anu saluyu
Ningali hasil analis
Ayeuna urang parantos ngalaksanakeun sareng ngonpigurasikeun ngawangun, hayu urang tingali sababaraha peringatan anu pikaresepeun anu aya dina proyék anu urang tingali.
Perhatosan 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;
}
analyzer The noticed kasalahan anu sanggeus dinamis allocating memori dina CreateObject, nalika aya pengecualian, mémori henteu diberesihan, sareng kabocoran mémori lumangsung.
Perhatosan 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),
....
};
Sababaraha urang salian ti analisa statik tiasa lulus tés attentiveness ieu. Conto salinan-témpél ieu saé pikeun alesan ieu.
Perhatosan N3
struct RCT12SpriteBase
{
....
uint8_t flags;
....
};
struct rct1_peep : RCT12SpriteBase
{
....
uint8_t flags;
....
};
Tangtosna, ngagunakeun variabel sareng nami anu sami dina kelas dasar sareng turunan henteu salawasna kasalahan. Sanajan kitu, téhnologi warisan sorangan nganggap yén sagala widang kelas indungna hadir dina kelas anak. Ku ngadéklarasikeun widang anu ngaranna sarua dina ahli waris, urang ngenalkeun kabingungan.
Perhatosan N4
void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
if ((imageDirection / 8) && (imageDirection / 8) != 3)
{
....
}
....
}
Hayu urang nempo leuwih deukeut. Ekspresi gambarArah/8 bakal palsu lamun gambarArah aya dina rentang ti -7 nepi ka 7. Bagian kadua: (gambarArah / 8) != 3 cék gambarArah keur di luar rentang: ti -31 nepi ka -24 jeung ti 24 nepi ka 31, mungguh. Sigana rada aneh mun kuring mariksa angka pikeun citakan dina rentang tangtu ku cara kieu na, sanajan euweuh kasalahan dina sapotong kode ieu, Abdi nyarankeun nulis balik kaayaan ieu janten langkung eksplisit. Ieu bakal ngagampangkeun kahirupan pikeun jalma anu bakal maca sareng ngajaga kode ieu.
Perhatosan 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;
....
}
....
}
Fragmén kode ieu paling dipikaresep diala ku dekompilasi. Lajeng, ditilik ku comment ditinggalkeun, bagian tina kode non-kerja dihapus. Tapi, masih aya sababaraha operasi anu tinggaleun kursorId, nu ogé teu make akal pikiran.
Perhatosan 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 ieu rada gampang dibenerkeun; anjeun ngan ukur kedah pariksa deui katilu kalina pamaen ka pointer null, atawa tambahkeun ka awak pernyataan kondisional. Abdi nyarankeun pilihan kadua:
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);
}
}
....
}
Perhatosan 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));
....
}
....
}
Anjeun tiasa nyingkirkeun garis kode anu hese dibaca dina hiji waktos sareng ngarengsekeun masalah sareng mariksa nullptr. Abdi nyarankeun ngarobih kode sapertos kieu:
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);
....
}
....
}
Perhatosan N8
void CustomListView::MouseUp(....)
{
....
if (!ColumnHeaderPressedCurrentState)
{
ColumnHeaderPressed = std::nullopt;
ColumnHeaderPressedCurrentState = false;
Invalidate();
}
}
Kodeu Sigana rada aneh. Sigana mah aya typo boh dina kaayaan atawa nalika ulang assigning variabel ColumnHeaderPressedCurrentState harti palsu.
kacindekan
Sakumaha anu urang tingali, ngahijikeun analisa statik PVS-Studio kana proyék TeamCity anjeun cukup saderhana. Jang ngalampahkeun ieu, cukup nulis ngan hiji file konfigurasi leutik. Mariksa kode bakal ngidinan Anjeun pikeun ngaidentipikasi masalah langsung saatos assembly, nu bakal nulungan ngaleungitkeun aranjeunna nalika pajeulitna sarta biaya parobahan masih low.
Upami anjeun hoyong ngabagikeun tulisan ieu ka pamiarsa anu nyarios basa Inggris, mangga nganggo tautan tarjamahan: Vladislav Stolyarov.
sumber: www.habr.com