PVS-Studio анализаторыг ашиглах хамгийн сүүлийн үеийн хувилбаруудын нэг бол түүнийг CI системтэй нэгтгэх явдал юм. Бараг ямар ч тасралтгүй интеграцийн системээс PVS-Studio төслийн дүн шинжилгээг хэдхэн тушаалд багтааж болох ч бид энэ үйл явцыг улам хялбар болгосоор байна. PVS-Studio нь анализаторын гаралтыг TeamCity - TeamCity Inspections Type формат руу хөрвүүлэх дэмжлэгтэй болсон. Энэ нь хэрхэн ажилладагийг харцгаая.
Ашигласан програм хангамжийн талаархи мэдээлэл
Судалж буй төслийн талаарх мэдээлэл
Энэ функцийг практик жишээн дээр туршиж үзье - OpenRCT2 төсөлд дүн шинжилгээ хийцгээе.
тохируулга
Цаг хэмнэхийн тулд би суулгах процессыг алгасаж, TeamCity серверийг компьютер дээрээ ажиллуулж эхлэхээс эхлэх байх. Бид: localhost:{суулгах явцад заасан порт} (миний хувьд localhost:9090) руу орж, зөвшөөрлийн өгөгдлийг оруулах шаардлагатай. Орсны дараа биднийг угтах болно:
Төсөл үүсгэх товчийг дарна уу. Дараа нь Гараар сонгоод талбаруудыг бөглөнө үү.
Товчлуур дарсны дараа бий болгох, биднийг тохиргоотой цонх угтан авна.
Дарцгаая Бүтээлийн тохиргоог үүсгэх.
Талбаруудыг бөглөж, товшино уу бий болгох. Бид таныг хувилбарын хяналтын системийг сонгохыг хүссэн цонхыг харж байна. Эх сурвалжууд аль хэдийн орон нутагт байрладаг тул дарна уу Алгасах.
Эцэст нь бид төслийн тохиргоо руу шилждэг.
Үүнийг хийхийн тулд угсрах алхмуудыг нэмж оруулцгаая: Бүтээх алхмууд -> Үүсгэх алхам нэмнэ.
Энд бид сонгоно:
- Гүйлтийн төрөл -> Командын мөр
- Ажиллуулах -> Тусгай скрипт
Төслийн эмхэтгэлийн явцад бид дүн шинжилгээ хийх тул угсрах, дүн шинжилгээ хийх нь нэг алхам байх ёстой тул талбарыг бөглөнө үү Захиалгат скрипт:
Бид дараа нь тусдаа алхамуудыг авч үзэх болно. Анализаторыг ачаалах, төслийг угсрах, дүн шинжилгээ хийх, тайлан гаргах, форматлахад ердөө арван нэгэн мөр код шаардагдах нь чухал юм.
Бидний хийх ёстой хамгийн сүүлийн зүйл бол орчны хувьсагчдыг тохируулах явдал бөгөөд би тэдгээрийн уншигдах чадварыг сайжруулах зарим арга замыг тодорхойлсон. Үүнийг хийхийн тулд цаашаа явцгаая: Параметрүүд -> Шинэ параметр нэмнэ гурван хувьсагч нэмнэ:
Та товчлуур дээр дарахад л хангалттай Run баруун дээд буланд. Төслийг угсарч, дүн шинжилгээ хийж байх хооронд би скриптийн талаар танд хэлэх болно.
Шууд скрипт
Эхлээд бид хамгийн сүүлийн үеийн PVS-Studio түгээлтийг татаж авах хэрэгтэй. Үүний тулд бид Chocolatey багц менежерийг ашигладаг. Энэ талаар илүү ихийг мэдэхийг хүсч буй хүмүүсийн хувьд харгалзах зүйл байна
choco install pvs-studio -y
Дараа нь CLMonitor төслийн бүтээн байгуулалтыг хянах хэрэгслийг ажиллуулцгаая.
%CLmon% monitor –-attach
Дараа нь бид төслийг орчны хувьсагч болгон барих болно MSB нь миний бүтээх ёстой MSBuild-ийн хувилбарт хүрэх зам юм
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
PVS-Studio-д нэвтрэх болон лицензийн түлхүүрийг оруулъя:
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
Бүтээж дууссаны дараа урьдчилан боловсруулсан файлууд болон статик шинжилгээг үүсгэхийн тулд CLMonitor-г дахин ажиллуулна уу:
%CLmon% analyze -l "c:ptest.plog"
Дараа нь бид түгээлтийн өөр хэрэгслийг ашиглах болно. PlogConverter нь тайланг стандарт форматаас TeamCity-д зориулсан формат руу хөрвүүлдэг. Үүний ачаар бид үүнийг бүтээх цонхноос шууд харах боломжтой болно.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
Сүүлийн алхам бол форматлагдсан тайланг харуулах явдал юм stdout, үүнийг TeamCity задлан шинжлэгч авах болно.
type "C:tempptest.plog_TeamCity.txt"
Бүрэн скрипт код:
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"
Энэ хооронд төслийн угсралт, дүн шинжилгээ амжилттай хийгдсэн тул бид таб руу орж болно Төслүүд мөн үүнд итгэлтэй байгаарай.
Одоо товшъё Хяналт шалгалт нийтанализаторын тайланг үзэхийн тулд:
Анхааруулгыг оношилгооны дүрмийн дугаараар бүлэглэв. Кодоор шилжихийн тулд та анхааруулга бүхий мөрийн дугаар дээр дарах хэрэгтэй. Баруун дээд буланд байгаа асуултын тэмдэг дээр дарснаар баримт бичиг бүхий шинэ таб нээгдэнэ. Та мөн анализаторын анхааруулга бүхий мөрийн дугаар дээр дарж кодоор шилжих боломжтой. Ашиглах үед алсын компьютерээс навигаци хийх боломжтой SourceTreeRoot тэмдэглэгээ. Анализаторын энэ горимыг сонирхож буй хэн бүхэн холбогдох хэсэгтэй танилцаж болно
Анализаторын үр дүнг харах
Одоо бид угсралтыг байрлуулж, тохируулж дууссаны дараа бидний үзэж буй төсөлд олдсон зарим сонирхолтой сэрэмжлүүлгийг харцгаая.
Анхааруулга 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;
}
Анализатор санах ойг динамикаар хуваарилсны дараа алдаа гарсныг анзаарав Объект үүсгэх, үл хамаарах зүйл тохиолдоход санах ой арилдаггүй бөгөөд санах ойн алдагдал үүсдэг.
Анхааруулга 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),
....
};
Статик анализатороос өөр цөөхөн хүн энэ анхааралтай байдлын шалгалтыг давж чадна. Энэ хуулж буулгах жишээ нь яг энэ шалтгааны улмаас тохиромжтой.
Анхааруулга N3
struct RCT12SpriteBase
{
....
uint8_t flags;
....
};
struct rct1_peep : RCT12SpriteBase
{
....
uint8_t flags;
....
};
Мэдээжийн хэрэг, ижил нэртэй хувьсагчийг үндсэн анги болон удамд ашиглах нь үргэлж алдаа биш юм. Гэсэн хэдий ч өв залгамжлалын технологи нь өөрөө эцэг эхийн ангийн бүх талбарууд хүүхдийн ангид байдаг гэж үздэг. Өв залгамжлагчид ижил нэртэй талбаруудыг зарласнаар бид төөрөгдөл үүсгэдэг.
Анхааруулга N4
void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
if ((imageDirection / 8) && (imageDirection / 8) != 3)
{
....
}
....
}
Илүү дэлгэрэнгүй харцгаая. Илэрхийлэл дүрсний чиглэл/8 бол худал болно зургийн чиглэл -7-оос 7-н хооронд байна. Хоёрдугаар хэсэг: (imageDirection / 8) != 3 шалгалтууд зургийн чиглэл хязгаараас гадуур байхын тулд: -31-ээс -24, 24-31 хүртэл. Ийм байдлаар тоонуудыг тодорхой мужид оруулахыг шалгах нь надад хачирхалтай санагдаж байгаа бөгөөд энэ кодонд алдаа гараагүй байсан ч илүү тодорхой болгохын тулд эдгээр нөхцлийг дахин бичихийг зөвлөж байна. Энэ нь энэ кодыг уншиж, хадгалах хүмүүсийн амьдралыг ихээхэн хөнгөвчлөх болно.
Анхааруулга 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;
....
}
....
}
Энэ кодын фрагментийг задлах замаар олж авсан байх магадлалтай. Дараа нь үлдээсэн сэтгэгдлээс харахад ажиллахгүй кодын нэг хэсгийг хассан. Гэсэн хэдий ч хэд хэдэн хагалгаа үлдээд байна курсорын дугаар, энэ нь бас нэг их утгагүй юм.
Анхааруулга 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); // <=
}
....
}
Энэ кодыг засахад маш хялбар тул та гурав дахь удаагаа шалгах хэрэгтэй тоглогч тэг заагч руу эсвэл нөхцөлт мэдэгдлийн үндсэн хэсэгт нэмнэ. Би хоёр дахь сонголтыг санал болгож байна:
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);
}
}
....
}
Анхааруулга 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));
....
}
....
}
Уншихад хэцүү кодын мөрийг нэг дороос салж, шалгах замаар асуудлыг шийдэж чадна. nullptr. Би кодыг дараах байдлаар өөрчлөхийг санал болгож байна.
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);
....
}
....
}
Анхааруулга N8
void CustomListView::MouseUp(....)
{
....
if (!ColumnHeaderPressedCurrentState)
{
ColumnHeaderPressed = std::nullopt;
ColumnHeaderPressedCurrentState = false;
Invalidate();
}
}
Код нь маш хачирхалтай харагдаж байна. Нөхцөлд эсвэл хувьсагчийг дахин оноож байх үед үсгийн алдаа гарсан юм шиг надад санагдаж байна ColumnHeaderPressedCurrentState утга хуурамч.
дүгнэлт
Бидний харж байгаагаар PVS-Studio статик анализаторыг TeamCity төсөлдөө нэгтгэх нь маш энгийн зүйл юм. Үүнийг хийхийн тулд зөвхөн нэг жижиг тохиргооны файл бичихэд хангалттай. Кодыг шалгах нь угсралтын дараа нэн даруй асуудлыг тодорхойлох боломжийг танд олгоно, энэ нь өөрчлөлтийн нарийн төвөгтэй байдал, өртөг бага хэвээр байгаа үед тэдгээрийг арилгахад тусална.
Хэрэв та энэ нийтлэлийг англи хэлээр ярьдаг үзэгчидтэй хуваалцахыг хүсвэл орчуулгын холбоосыг ашиглана уу: Владислав Столяров.
Эх сурвалж: www.habr.com