PVS-Studio analizatzailea erabiltzeko egungo eszenatokietako bat CI sistemekin integratzea da. Eta PVS-Studio proiektu baten analisia etengabeko integrazio-sistema ia edozeinetik komando gutxitan eraiki daitekeen arren, prozesu hau are erosoagoa egiten jarraitzen dugu. PVS-Studio-k orain analizatzaileen irteera TeamCity - TeamCity Inspections Mota formatu batean bihurtzeko laguntza du. Ea nola funtzionatzen duen.
Erabilitako softwareari buruzko informazioa
Aztergai dugun proiektuari buruzko informazioa
Proba dezagun funtzionalitate hau adibide praktiko batean; azter dezagun OpenRCT2 proiektua.
doikuntza
Denbora aurrezteko, ziurrenik instalazio-prozesua saltatuko dut eta TeamCity zerbitzaria ordenagailuan exekutatzen dudan momentutik hasiko naiz. Hona joan behar dugu: localhost:{instalazio prozesuan zehaztutako ataka} (nire kasuan, localhost:9090) eta baimen-datuak sartu. Sartu ondoren honako hauek hartuko gaituzte:
Egin klik Sortu proiektua botoian. Ondoren, hautatu Eskuz eta bete eremuak.
Botoia sakatu ondoren Sortu, ezarpenak dituen leiho batek agurtzen gaitu.
Egin dezagun klik Sortu konfigurazio konfigurazioa.
Bete eremuak eta egin klik Sortu. Leiho bat ikusten dugu bertsio-kontrol sistema bat hautatzeko eskatzen dizuna. Iturburuak lokalean kokatuta daudenez, egin klik Salto egin.
Azkenik, proiektuaren ezarpenetara joango gara.
Gehitu ditzagun muntaketa-urratsak, klik hau egiteko: Eraiki urratsak -> Gehitu eraikuntza urratsa.
Hemen aukeratzen dugu:
- Korrikalari mota -> Komando-lerroa
- Exekutatu -> Script pertsonalizatua
Proiektuaren konpilazioan analisia egingo dugunez, muntaia eta analisia urrats bat izan beharko lukete, beraz, bete eremua Script pertsonalizatua:
Aurrerago urrats indibidualak aztertuko ditugu. Garrantzitsua da analizatzailea kargatu, proiektua muntatu, aztertu, txostena atera eta formateatzea hamaika kode-lerro baino ez izatea.
Egin behar dugun azken gauza ingurune-aldagaiak ezartzea da, irakurgarritasuna hobetzeko modu batzuk azaldu ditut. Horretarako, aurrera goazen: Parametroak -> Gehitu parametro berria eta gehitu hiru aldagai:
Egin behar duzun guztia botoia sakatzea da Korrika egin goiko eskuineko izkinan. Proiektua muntatzen eta aztertzen ari diren bitartean, gidoiaren berri emango dizuet.
Zuzenean gidoia
Lehenik eta behin, azken PVS-Studio banaketa deskargatu behar dugu. Horretarako Chocolatey pakete kudeatzailea erabiltzen dugu. Honi buruz gehiago jakin nahi duenarentzat, dago dagokion bat
choco install pvs-studio -y
Ondoren, abiarazi dezagun CLMonitor proiektuaren jarraipena egiteko erabilgarritasuna.
%CLmon% monitor β-attach
Ondoren, proiektua ingurune-aldagai gisa eraikiko dugu MSB eraiki behar dudan MSBuild bertsiorako bidea da
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
Sar ditzagun PVS-Studiorako saioa hasteko eta lizentzia-gakoa:
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
Eraikuntza amaitu ondoren, exekutatu CLMonitor berriro aurreprozesatutako fitxategiak eta analisi estatikoa sortzeko:
%CLmon% analyze -l "c:ptest.plog"
Ondoren, gure banaketako beste erabilgarritasun bat erabiliko dugu. PlogConverter-ek txosten bat formatu estandar batetik TeamCity-ren formatu espezifiko batera bihurtzen du. Horri esker, zuzenean ikusi ahal izango dugu eraikuntza-leihoan.
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
Azken urratsa formateatutako txostena bistaratzea da stdout, non TeamCity analizatzaileak jasoko du.
type "C:tempptest.plog_TeamCity.txt"
Gidoi-kode osoa:
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"
Bitartean, proiektuaren muntaia eta analisia arrakastaz burutu da, fitxara joan gaitezke Proiektuak eta ziurtatu.
Orain klik egin dezagun Ikuskapenak Guztiraanalizatzailearen txostena ikustera joateko:
Abisuak diagnostiko-arau-zenbakien arabera multzokatzen dira. Kodean zehar nabigatzeko, abisua duen lerro-zenbakian klik egin behar duzu. Goiko eskuineko izkinan dagoen galdera ikurrean klik eginez fitxa berri bat irekiko zaizu dokumentazioarekin. Kodean zehar nabiga dezakezu analizatzailearen abisua duen lerro-zenbakian klik eginez. Erabiltzean urruneko ordenagailu batetik nabigatzea posible da SourceTreeRoot markatzailea. Analizatzailearen funtzionamendu-modu honetan interesa duen edonork dagokion atala ezagutu dezake
Analizatzailearen emaitzak ikustea
Orain, eraikuntza inplementatu eta konfiguratzen amaitu dugula, ikus ditzagun ikusten ari garen proiektuan aurkitutako abisu interesgarri batzuei.
Abisua 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;
}
Analizatzaileak errore bat ikusi zuen memoria dinamikoki esleitu ondoren SortuObjektua, salbuespen bat gertatzen denean, memoria ez da garbitzen eta memoria ihesa gertatzen da.
Abisua 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),
....
};
Analizatzaile estatiko bat ez den jende gutxik gainditu lezake arreta proba hau. Kopiatu-itsatsi adibide hau ona da, hain zuzen ere arrazoi horregatik.
Abisuak N3
struct RCT12SpriteBase
{
....
uint8_t flags;
....
};
struct rct1_peep : RCT12SpriteBase
{
....
uint8_t flags;
....
};
Noski, oinarrizko klasean eta ondorengoan izen bereko aldagai bat erabiltzea ez da beti errore bat. Hala ere, oinordetza-teknologiak berak suposatzen du klase nagusiaren eremu guztiak haurraren klasean daudela. Oinordetzan izen bereko eremuak deklaratuz, nahasmena sortzen dugu.
Abisua N4
void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
if ((imageDirection / 8) && (imageDirection / 8) != 3)
{
....
}
....
}
Ikus dezagun hurbilagotik. Adierazpena irudiaren Zuzendaritza/8 faltsua izango da baldin irudiaren Zuzendaritza -7tik 7ra bitartekoa da. Bigarren zatia: (irudiaNorabidea / 8) != 3 txekeak irudiaren Zuzendaritza tartetik kanpo egoteagatik: -31tik -24ra eta 24tik 31ra, hurrenez hurren. Nahiko arraroa iruditzen zait modu honetan zenbakiak tarte jakin batean sartzen diren egiaztatzea eta, kode zati honetan akatsik ez badago ere, baldintza hauek berridaztea gomendatuko nuke esplizituago izateko. Horrek bizitza askoz erraztuko luke kode hau irakurri eta mantenduko luketen pertsonei.
Abisua 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;
....
}
....
}
Kode zati hau deskonpilazio bidez lortu zen ziurrenik. Ondoren, utzitako iruzkinaren arabera, funtzionatzen ez zuen kodearen zati bat kendu zen. Hala ere, oraindik pare bat operazio geratzen dira kurtsoreId, eta horrek ere ez dauka zentzu handirik.
Abisua 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 hau nahiko erraza da zuzentzen; hirugarren aldiz egiaztatu besterik ez duzu behar Jokalari Erakusle nulu bati edo gehitu baldintzazko adierazpenaren gorputzean. Bigarren aukera proposatuko nuke:
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);
}
}
....
}
Abisua 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));
....
}
....
}
Irakurtzen zaila den kode-lerro bat kolpe bakarrean ken dezakezu eta egiaztatzearekin arazoa konpondu dezakezu. nullptr. Kodea honela aldatzea proposatzen dut:
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);
....
}
....
}
Abisua N8
void CustomListView::MouseUp(....)
{
....
if (!ColumnHeaderPressedCurrentState)
{
ColumnHeaderPressed = std::nullopt;
ColumnHeaderPressedCurrentState = false;
Invalidate();
}
}
Kodeak nahiko arraroa dirudi. Iruditzen zait akats bat egon zela egoeran edo aldagaia berriro esleitzean ColumnHeaderPressedCurrentState esanahia false.
Irteera
Ikus dezakegunez, PVS-Studio analizatzaile estatikoa zure TeamCity proiektuan integratzea nahiko erraza da. Horretarako, nahikoa da konfigurazio fitxategi txiki bakarra idaztea. Kodea egiaztatzeak muntatu eta berehala arazoak identifikatu ahal izango dituzu, eta horrek ezabatzen lagunduko du aldaketen konplexutasuna eta kostua oraindik txikia denean.
Artikulu hau ingelesez hitz egiten duen publiko batekin partekatu nahi baduzu, mesedez, erabili itzulpen esteka: Vladislav Stolyarov.
Iturria: www.habr.com