PVS-Studio анализаторун колдонуунун эң учурдагы сценарийлеринин бири анын CI системалары менен интеграциясы болуп саналат. PVS-Studio долбоорун талдоо дээрлик бардык үзгүлтүксүз интеграция тутумунан бир нече буйруктарга курулса да, биз бул процессти ого бетер ыңгайлуу кылууну улантабыз. PVS-Studio азыр анализатордун чыгышын TeamCity - TeamCity Inspections Type форматына айландырууну колдойт. Келгиле, анын кантип иштээрин карап көрөлү.
Колдонулган программалык камсыздоо жөнүндө маалымат
изилденип жаткан долбоор жөнүндө маалымат
Келгиле, бул функцияны практикалык мисалда сынап көрөлү - OpenRCT2 долбоорун талдап көрөлү.
тууралоо
Убакытты үнөмдөө үчүн, балким, орнотуу процессин өткөрүп жиберип, компьютеримде TeamCity сервери иштеп баштагандан баштап баштайм. Бизге барышыбыз керек: localhost:{орнотуу процессинде көрсөтүлгөн порт} (менин учурда, localhost:9090) жана авторизация дайындарын киргизишибиз керек. Киргенден кийин бизди тосуп алат:
Долбоор түзүү баскычын чыкылдатыңыз. Андан кийин, Кол менен тандап, талааларды толтуруңуз.
кнопкасын баскандан кийин түзүү, бизди орнотуулары бар терезе тосуп алат.
келгиле Куруу конфигурациясын түзүү.
Талааларды толтуруңуз жана басыңыз түзүү. Биз версияны башкаруу тутумун тандоону суранган терезени көрөбүз. Булактар мурунтан эле жергиликтүү жайгашкандыктан, чыкылдатыңыз секирүү.
Акыр-аягы, биз долбоордун жөндөөлөрүнө өтүү.
Бул чыкылдатуу үчүн, монтаждоо кадамдарын кошолу: Куруу кадамдары -> Куруу кадамын кошуу.
Бул жерде биз тандайбыз:
- Runner түрү -> Command Line
- Run -> Ыңгайлаштырылган скрипт
Биз долбоорду түзүү учурунда талдоо жүргүзө тургандыктан, чогултуу жана талдоо бир кадам болушу керек, андыктан талааны толтуруңуз Көнүмүш Script:
Биз кийинчерээк жеке кадамдарды карап чыгабыз. Анализаторду жүктөө, долбоорду чогултуу, аны талдоо, отчетту чыгаруу жана аны форматтоо үчүн он бир гана сап код талап кылынышы маанилүү.
Биз кылышыбыз керек болгон акыркы нерсе - бул чөйрө өзгөрмөлөрүн коюу, мен алардын окулушун жакшыртуунун бир нече жолдорун белгиледим. Бул үчүн, келгиле, уланталы: Параметрлер -> Жаңы параметр кошуу жана үч өзгөрмө кошуу:
Болгону баскычты бассаңыз болот 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;
}
Анализатор эстутумду динамикалык бөлүштүргөндөн кийин катаны байкады CreateObject, өзгөчө кырдаал болгондо, эс тазаланбайт жана эс тутумдун агып кетиши пайда болот.
Эскертүү 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)
{
....
}
....
}
Келгиле, кененирээк карап көрөлү. Экспресс imageDirection/8 болсо жалган болот imageDirection -7ден 7ге чейинки диапазондо. Экинчи бөлүк: (imageDirection / 8) != 3 чектер imageDirection диапазондон тышкары болгондугу үчүн: тиешелүүлүгүнө жараша -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;
....
}
....
}
Бул код фрагменти, кыязы, декомпиляция жолу менен алынган. Андан кийин, калтырылган комментарийге караганда, иштебеген коддун бир бөлүгү алынып салынды. Бирок дагы бир нече операция калды cursorId, бул да көп мааниге ээ эмес.
Эскертүү 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 долбооруна интеграциялоо абдан жөнөкөй. Бул үчүн, бир эле кичинекей конфигурация файлын жазуу жетиштүү. Кодду текшерүү көйгөйлөрдү чогулткандан кийин дароо аныктоого мүмкүндүк берет, бул өзгөртүүлөрдүн татаалдыгы жана баасы дагы эле төмөн болгон учурда аларды жоюуга жардам берет.
Бул макаланы англис тилдүү аудитория менен бөлүшкүңүз келсе, котормо шилтемесин колдонуңуз: Владислав Столяров.
Source: www.habr.com