PVS-Studio ๋ถ์๊ธฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฐ์ฅ ์ต๊ทผ์ ์๋๋ฆฌ์ค ์ค ํ๋๋ CI ์์คํ
๊ณผ์ ํตํฉ์
๋๋ค. ๊ฑฐ์ ๋ชจ๋ ์ฐ์ ํตํฉ ์์คํ
์ PVS-Studio ํ๋ก์ ํธ ๋ถ์์ ๋จ ๋ช ๊ฐ์ง ๋ช
๋ น์ผ๋ก ๊ตฌ์ถ๋ ์ ์์ง๋ง ์ฐ๋ฆฌ๋ ์ด ํ๋ก์ธ์ค๋ฅผ ๋์ฑ ํธ๋ฆฌํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๊ณ์ ๋
ธ๋ ฅํ๊ณ ์์ต๋๋ค. PVS-Studio๋ ์ด์ ๋ถ์๊ธฐ ์ถ๋ ฅ์ TeamCity ํ์(TeamCity Inspections Type)์ผ๋ก ๋ณํํ๋ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค. ๊ทธ๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ด
์๋ค.
์ฌ์ฉ๋ ์ํํธ์จ์ด์ ๋ํ ์ ๋ณด
์ฐ๊ตฌ์ค์ธ ํ๋ก์ ํธ์ ๋ํ ์ ๋ณด
์ค์ ์ฌ๋ก์์ ์ด ๊ธฐ๋ฅ์ ์ํํด ๋ณด๊ฒ ์ต๋๋ค. OpenRCT2 ํ๋ก์ ํธ๋ฅผ ๋ถ์ํด ๋ณด๊ฒ ์ต๋๋ค.
์กฐ์
์๊ฐ์ ์ ์ฝํ๊ธฐ ์ํด ์ค์น ๊ณผ์ ์ ๊ฑด๋๋ฐ๊ณ ์ปดํจํฐ์์ TeamCity ์๋ฒ๊ฐ ์คํ๋๋ ์๊ฐ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค. localhost:{์ค์น ํ๋ก์ธ์ค ์ค์ ์ง์ ๋ ํฌํธ}(์ ๊ฒฝ์ฐ์๋ localhost:9090)๋ก ์ด๋ํ์ฌ ์ธ์ฆ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํด์ผ ํฉ๋๋ค. ์ ์ฅ ํ ์ฐ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ์ธ์ฌ๋ฅผ ๋ฐ๊ฒ ๋ ๊ฒ์ ๋๋ค:
ํ๋ก์ ํธ ์์ฑ ๋ฒํผ์ ํด๋ฆญํ์ธ์. ๊ทธ๋ฐ ๋ค์ ์๋์ ์ ํํ๊ณ ํ๋๋ฅผ ์ฑ์๋๋ค.
๋ฒํผ์ ๋๋ฅธ ํ ๋ง๋ค๊ธฐ, ์ค์ ์ฐฝ์ด ๋ํ๋ฉ๋๋ค.
ํด๋ฆญํด๋ณด์ ๋น๋ ๊ตฌ์ฑ ๋ง๋ค๊ธฐ.
ํ๋๋ฅผ ์ฑ์ฐ๊ณ ํด๋ฆญํ์ธ์. ๋ง๋ค๊ธฐ. ๋ฒ์ ์ ์ด ์์คํ
์ ์ ํํ๋ผ๋ ์ฐฝ์ด ํ์๋ฉ๋๋ค. ์์ค๋ ์ด๋ฏธ ๋ก์ปฌ์ ์์ผ๋ฏ๋ก ๊ฑด๋๋ฐ๊ธฐ.
๋ง์ง๋ง์ผ๋ก ํ๋ก์ ํธ ์ค์ ์ผ๋ก ์ด๋ํฉ๋๋ค.
์กฐ๋ฆฝ ๋จ๊ณ๋ฅผ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฅผ ์ํํ๋ ค๋ฉด ๋ค์์ ํด๋ฆญํ์ธ์. ๋น๋ ๋จ๊ณ -> ๋น๋ ๋จ๊ณ ์ถ๊ฐ.
์ฌ๊ธฐ์๋ ๋ค์์ ์ ํํฉ๋๋ค.
- ๋ฌ๋ ์ ํ -> ๋ช ๋ น์ค
- ์คํ -> ์ฌ์ฉ์ ์ ์ ์คํฌ๋ฆฝํธ
ํ๋ก์ ํธ ์ปดํ์ผ ๊ณผ์ ์์ ๋ถ์์ ์ํํ๊ธฐ ๋๋ฌธ์ ์กฐ๋ฆฝ๊ณผ ๋ถ์์ด ํ ๋จ๊ณ๋ก ์ด๋ฃจ์ด์ ธ์ผ ํ๋ฏ๋ก ํด๋น ํ๋๋ฅผ ์ฑ์์ฃผ์ธ์. ์ฌ์ฉ์ ์ ์ ์คํฌ๋ฆฝํธ:
๋์ค์ ๊ฐ๋ณ ๋จ๊ณ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๋ถ์๊ธฐ ๋ก๋, ํ๋ก์ ํธ ์กฐ๋ฆฝ, ๋ถ์, ๋ณด๊ณ ์ ์ถ๋ ฅ ๋ฐ ํ์ ์ง์ ์ ๋จ XNUMX์ค์ ์ฝ๋๋ง ํ์ํ๋ค๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก ํด์ผ ํ ์ผ์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ๋ ๊ฒ์ ๋๋ค. ์ด์ ๋ํ ๊ฐ๋ ์ฑ์ ํฅ์์ํค๋ ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ค๋ช ํ์ต๋๋ค. ์ด๋ฅผ ์ํด ๋ค์์ผ๋ก ๋์ด๊ฐ๊ฒ ์ต๋๋ค. ๋งค๊ฐ๋ณ์ -> ์ ๋งค๊ฐ๋ณ์ ์ถ๊ฐ ์ธ ๊ฐ์ง ๋ณ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
๋ฒํผ์ ๋๋ฅด๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค ๋ฌ๋ฆฌ๊ธฐ ์ค๋ฅธ์ชฝ ์๋จ์ ์์ต๋๋ค. ํ๋ก์ ํธ๊ฐ ๊ตฌ์ฑ๋๊ณ ๋ถ์๋๋ ๋์ ์คํฌ๋ฆฝํธ์ ๋ํด ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
์ง์ ์คํฌ๋ฆฝํธ
๋จผ์ ์ต์ 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"
๋ง์ง๋ง ๋จ๊ณ๋ ํ์์ด ์ง์ ๋ ๋ณด๊ณ ์๋ฅผ ํ์ํ๋ ๊ฒ์ ๋๋ค. ํ์ค ์ถ๋ ฅ, 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"
๊ทธ๋์ ํ๋ก์ ํธ์ ์กฐ๋ฆฝ ๋ฐ ๋ถ์์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ผ๋ฏ๋ก ํญ์ผ๋ก ์ด๋ํ ์ ์์ต๋๋ค. ํ๋ก์ ํธ ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ํ์ธํ์ญ์์ค.
์ด์ ๋ค์์ ํด๋ฆญํด ๋ณผ๊น์? ๊ฒ์ฌ ์ด๊ณ๋ถ์๊ธฐ ๋ณด๊ณ ์๋ฅผ ๋ณด๋ ค๋ฉด ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์.
๊ฒฝ๊ณ ๋ ์ง๋จ ๊ท์น ๋ฒํธ๋ณ๋ก ๊ทธ๋ฃนํ๋ฉ๋๋ค. ์ฝ๋๋ฅผ ํ์ํ๋ ค๋ฉด ๊ฒฝ๊ณ ๊ฐ ์๋ ์ค ๋ฒํธ๋ฅผ ํด๋ฆญํด์ผ ํฉ๋๋ค. ์ค๋ฅธ์ชฝ ์๋จ์ ์๋ ๋ฌผ์ํ๋ฅผ ํด๋ฆญํ๋ฉด ๋ฌธ์๊ฐ ํฌํจ๋ ์ ํญ์ด ์ด๋ฆฝ๋๋ค. ๋ถ์๊ธฐ ๊ฒฝ๊ณ ๊ฐ ์๋ ์ค ๋ฒํธ๋ฅผ ํด๋ฆญํ์ฌ ์ฝ๋๋ฅผ ํ์ํ ์๋ ์์ต๋๋ค. ์ฌ์ฉ ์ ์๊ฒฉ ์ปดํจํฐ์์ ํ์์ด ๊ฐ๋ฅํฉ๋๋ค. ์์คํธ๋ฆฌ๋ฃจํธ ์ฑ์ ์. ์ด ๋ถ์๊ธฐ ์๋ ๋ชจ๋์ ๊ด์ฌ์ด ์๋ ์ฌ๋์ ๋๊ตฌ๋ ํด๋น ์น์
์ ์์งํ ์ ์์ต๋๋ค.
๋ถ์๊ธฐ ๊ฒฐ๊ณผ ๋ณด๊ธฐ
์ด์ ๋น๋ ๋ฐฐํฌ ๋ฐ ๊ตฌ์ฑ์ด ์๋ฃ๋์์ผ๋ฏ๋ก ์ฐ๋ฆฌ๊ฐ ๋ณด๊ณ ์๋ ํ๋ก์ ํธ์์ ๋ฐ๊ฒฌ๋ ๋ช ๊ฐ์ง ํฅ๋ฏธ๋ก์ด ๊ฒฝ๊ณ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๊ฒฝ๊ณ 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)
{
....
}
....
}
์ข ๋ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ํํ ์ด๋ฏธ์ง๋ฐฉํฅ/8 ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ ๊ฑฐ์ง์ด ๋ฉ๋๋ค. ์ด๋ฏธ์ง๋ฐฉํฅ ๋ฒ์๋ -7์์ 7 ์ฌ์ด์ ๋๋ค. ๋ ๋ฒ์งธ ๋ถ๋ถ: (์ด๋ฏธ์ง ๋ฐฉํฅ / 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;
....
}
....
}
์ด ์ฝ๋ ์กฐ๊ฐ์ ๋์ปดํ์ผ์ ํตํด ์ป์ ๊ฒ์ผ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ผ์ชฝ ์ฃผ์์ผ๋ก ํ๋จํ๋ฉด ์๋ํ์ง ์๋ ์ฝ๋์ ์ผ๋ถ๊ฐ ์ ๊ฑฐ๋์์ต๋๋ค. ํ์ง๋ง ์์ง ๋ช ๊ฐ์ง ์์ ์ด ๋จ์์ต๋๋ค. ์ปค์ID, ๊ทธ๊ฒ๋ ๋ณ๋ก ์๋ฏธ๊ฐ ์์ต๋๋ค.
๊ฒฝ๊ณ 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 ํ๋ก์ ํธ์ ํตํฉํ๋ ๊ฒ์ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ์์ ๊ตฌ์ฑ ํ์ผ ํ๋๋ง ์์ฑํ๋ฉด ์ถฉ๋ถํฉ๋๋ค. ์ฝ๋๋ฅผ ํ์ธํ๋ฉด ์กฐ๋ฆฝ ์งํ ๋ฌธ์ ๋ฅผ ์๋ณํ ์ ์์ผ๋ฏ๋ก ๋ณต์ก์ฑ๊ณผ ๋ณ๊ฒฝ ๋น์ฉ์ด ์ฌ์ ํ ๋ฎ์ ๋ ๋ฌธ์ ๋ฅผ ์ ๊ฑฐํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์ด ๊ธฐ์ฌ๋ฅผ ์์ด๊ถ ์ฒญ์ค๊ณผ ๊ณต์ ํ๋ ค๋ฉด ๋ฒ์ญ ๋งํฌ์ธ Vladislav Stolyarov๋ฅผ ์ฌ์ฉํ์ญ์์ค.
์ถ์ฒ : habr.com