د PVS-Studio شنونکي کارولو لپاره یو له خورا اوسني سناریو څخه د CI سیسټمونو سره د هغې ادغام دی. او که څه هم د نږدې هر دوامداره ادغام سیسټم څخه د PVS-Studio پروژې تحلیل یوازې په یو څو کمانډونو کې رامینځته کیدی شي ، موږ دې پروسې ته لا نور هم اسانه کولو ته دوام ورکوو. PVS-Studio اوس د ټیمCity - TeamCity تفتیش ډول لپاره په بڼه کې د تحلیلي محصول بدلولو لپاره ملاتړ لري. راځئ وګورو چې دا څنګه کار کوي.
د کارول شوي سافټویر په اړه معلومات
د مطالعې لاندې پروژې په اړه معلومات
راځئ چې دا فعالیت په عملي مثال کې هڅه وکړو - راځئ چې د OpenRCT2 پروژه تحلیل کړو.
تعدیلات
د وخت خوندي کولو لپاره ، زه به شاید د نصب کولو پروسه پریږدم او له هغه شیبې څخه پیل وکړم کله چې زه د ټیم سیټي سرور زما په کمپیوټر کې روان وي. موږ اړتیا لرو چې لاړ شو: localhost:{د نصب کولو پروسې په جریان کې مشخص شوی پور} (زما په قضیه کې ، localhost: 9090) او د اختیار کولو ډاټا داخل کړئ. د ننوتلو وروسته به موږ ته ښه راغلاست وایو:
د پروژې جوړولو تڼۍ کلیک وکړئ. بیا، په لاسي ډول غوره کړئ او ساحې ډک کړئ.
د تڼۍ فشار وروسته جوړول، موږ د ترتیباتو سره د یوې کړکۍ لخوا ښه راغلاست وایو.
راځئ چې کلیک وکړو د جوړونې تشکیلات جوړ کړئ.
ساحې ډک کړئ او کلیک وکړئ جوړول. موږ یوه کړکۍ ګورو چې تاسو څخه د نسخې کنټرول سیسټم غوره کولو غوښتنه کوي. څرنګه چې سرچینې دمخه په ځایی توګه موقعیت لري، کلیک وکړئ پرېښودل.
په نهایت کې ، موږ د پروژې ترتیباتو ته ځو.
راځئ چې د مجلس مرحلې اضافه کړو، د دې کولو لپاره کلیک وکړئ: د جوړولو مرحلې -> د جوړیدو مرحله اضافه کړئ.
دلته موږ غوره کوو:
- د رنر ډول -> د کمانډ لاین
- چلول -> دودیز سکریپټ
څرنګه چې موږ به د پروژې تالیف په جریان کې تحلیل ترسره کړو، مجلس او تحلیل باید یو ګام وي، نو ساحه ډکه کړئ دودیز سکریټ:
موږ به وروسته انفرادي ګامونه وګورو. دا مهمه ده چې د تحلیل کونکي بار کول، د پروژې راټولول، تحلیل کول، د راپور تولیدول او فارمیټ کول یوازې د کوډ یوولس کرښې اخلي.
وروستی شی چې موږ یې کولو ته اړتیا لرو د چاپیریال متغیرات تنظیم کول دي ، کوم چې ما د دوی د لوستلو وړتیا ښه کولو لپاره ځینې لارې په ګوته کړې. د دې کولو لپاره، راځئ چې حرکت وکړو: پیرامیټونه -> نوی پیرامیټر اضافه کړئ او درې متغیرونه اضافه کړئ:
ټول هغه څه چې تاسو یې باید وکړئ تڼۍ فشار کړئ د دويم په پورتنۍ ښیې کونج کې. پداسې حال کې چې پروژه راټولیږي او تحلیل کیږي، زه به تاسو ته د سکریپټ په اړه ووایم.
په مستقیم ډول سکریپټ
لومړی، موږ اړتیا لرو چې د وروستي PVS-Studio ویش ډاونلوډ کړئ. د دې لپاره موږ د چاکلیټ کڅوړه مدیر کاروو. د هغو کسانو لپاره چې غواړي په دې اړه نور معلومات ترلاسه کړي، یو ورته دی
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 یو راپور د معیاري ب formatې څخه د ټیم ښار ځانګړي ب formatه ته بدلوي. د دې څخه مننه ، موږ به وکولی شو دا په مستقیم ډول د جوړونې کړکۍ کې وګورو.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
وروستی ګام دا دی چې فارمیټ شوی راپور په کې ښکاره کړئ stdout، چیرې چې دا به د ټیم سیټي پارسر لخوا غوره شي.
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;
....
}
....
}
دا کوډ ټوټه ډیری احتمال د تخریب کولو له لارې ترلاسه شوې. بیا، د تبصرې په واسطه قضاوت کول، د غیر کاري کوډ یوه برخه لیرې شوه. په هرصورت، لاهم یو څو عملیات پاتې دي 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- سټوډیو جامد تحلیل کونکي ادغام خورا ساده دی. د دې کولو لپاره، دا کافي ده چې یوازې یو کوچنی ترتیب فایل ولیکئ. د کوډ چک کول به تاسو ته اجازه درکړي چې د غونډې وروسته سمدستي ستونزې وپیژني، کوم چې به د دوی له منځه وړلو کې مرسته وکړي کله چې د بدلونونو پیچلتیا او لګښت لاهم ټیټ وي.
که تاسو غواړئ دا مقاله د انګلیسي ژبو لیدونکو سره شریکه کړئ، مهرباني وکړئ د ژباړې لینک وکاروئ: ولادیسلاو سټولیاروف.
سرچینه: www.habr.com