We all do code reviews. Who doesn't admit this – does it twice as often. C++ code reviewers look like a sapper. .. except that they can make a mistake more than once. But sometimes the consequences are painful . Brave code review world.
C++ Code as Seen by a Hypercritical
Reviewer
Phillip Khandeliants
khandeliants@viva64.com
About Me
A lead C++/C# developer at PVS-
Studio.
I’ve been developing the C++
analyzer’s core for 3 years.
I educate on modern C++.
2
Текст слайда
What are you talking about?
4
We all do code reviews
What are you talking about?
5
We all do code reviews
Who doesn't admit this – does it
twice as often
What are you talking about?
6
We all do code reviews
Who doesn't admit this – does it
twice as often
C++ code reviewers look like a sapper
What are you talking about?
7
We all do code reviews
Who doesn't admit this – does it
twice as often
C++ code reviewers look like a sapper
... except that they can make a
mistake more than once
We all do code reviews
Who doesn't admit this – does it
twice as often
C++ code reviewers look like a sapper
... except that they can make a
mistake more than once
But sometimes the consequences
are painful
What are you talking about?
8
void foo(const std::vector<....> &vec)
{
....
for (int i = 0; i < vec.size(); ++i) // 64-bit problems :)
{
// do some magic with vec[i]
....
}
....
}
12
void foo(const std::vector<....> &vec)
{
....
for (size_t i = 0; i < vec.size(); ++i) // ok
{
// do some magic with vec[i]
....
}
....
}
13
void foo(const std::vector<....> &vec)
{
....
for (std::vector<....>::size_type i = 0; i < vec.size(); ++i)
{
// do some magic with vec[i]
....
}
....
}
14
void foo(const std::vector<....> &vec)
{
....
for (auto i = 0uLL; i < vec.size(); ++i) // don't do that on
// 128-bit processors
{
// do some magic with vec[i]
....
}
....
}
15
void foo(const std::vector<....> &vec)
{
....
for (auto i = 0uLLL; i < vec.size(); ++i) // ok since C++7d
{
// do some magic with vec[i]
....
}
....
}
16
void foo(const std::vector<....> &vec)
{
....
for (auto i = 0uLLL; i < vec.size(); ++i) // ok since C++7d
{
// do some magic with vec[i]
....
}
....
}
17
void vector8_inc(std::vector<uint8_t> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
v[i]++;
}
}
void vector8_inc(std::vector<uint8_t> &v)
{
auto it = v.begin();
const auto end = v.end();
for (; it != end; ++it)
{
++(*it);
}
}
30
31
vector8_inc(std::vector<uint8_t> &):
mov rax, QWORD PTR [rdi] ; it = begin()
mov rdx, QWORD PTR [rdi+8] ; end = end()
cmp rax, rdx ; if (it == end)
je .L1 ; return
.L3: ; do {
add BYTE PTR [rax], 1 ; ++(*it)
add rax, 1 ; ++it
cmp rax, rdx ; } while (it != end)
.L1:
ret
32
vector8_inc(std::vector<uint8_t> &):
mov rax, QWORD PTR [rdi] ; it = begin()
mov rdx, QWORD PTR [rdi+8] ; end = end()
cmp rax, rdx ; if (it == end)
je .L1 ; return
.L3: ; do {
add BYTE PTR [rax], 1 ; ++(*it)
add rax, 1 ; ++it
cmp rax, rdx ; } while (it != end)
.L1:
ret
static void G584_CollectExprInfo(const Ptree *p,
vector<G584_Info> &infs)
{
....
auto what = p->What();
if (what == ntParenExpr)
{
// Remember the expression in parentheses and continue
infs.emplace_back(p, true, true, false, false); // ok since C++20
p = SafeSkipParentesis(p);
}
....
}
108
void AddFunctionDangerousInfo(const vstring &strFunctionInfo,
const FunctionDangerousInfo &info)
{
FunctionDangerousInfoMap &infoMap = GetFunctionDangerousInfoMap();
DangerousInfoIterator it = infoMap.find(strFunctionInfo);
if (it == infoMap.end())
{
infoMap.insert(make_pair(strFunctionInfo, dangerousInfo));
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
111
void AddFunctionDangerousInfo(const vstring &strFunctionInfo,
const FunctionDangerousInfo &info)
{
FunctionDangerousInfoMap &infoMap = GetFunctionDangerousInfoMap();
DangerousInfoIterator it = infoMap.find(strFunctionInfo);
if (it == infoMap.end())
{
infoMap.insert(make_pair(strFunctionInfo, dangerousInfo));
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
112
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.find(strFunctionInfo); it == infoMap.end())
{
infoMap.emplace(strFunctionInfo, dangerousInfo);
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
113
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.find(strFunctionInfo); it == infoMap.end())
{
infoMap.emplace(strFunctionInfo, dangerousInfo);
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
114
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.lower_bound(strFunctionInfo);
it != infoMap.end())
{
auto &a = it->second;
// some works with 'a'
}
else
{
infoMap.emplace_hint(it,
strFunctionInfo,
dangerousInfo);
}
}
115
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.lower_bound(strFunctionInfo);
it != infoMap.end() && it->first == strFunctionInfo)
{
auto &a = it->second;
// some works with 'a'
}
else
{
infoMap.emplace_hint(it,
strFunctionInfo,
dangerousInfo);
}
}
116
struct Foo
{
int i;
double d;
};
Foo* bar()
{
Foo *ptr = (Foo *) malloc(sizeof(Foo));
if (ptr == NULL)
return NULL;
ptr->i = 0; // ok in C, UB in C++
ptr->d = 0.0; // ok in C, UB in C++
return ptr;
}
119
struct Foo
{
int i;
double d;
};
Foo* bar()
{
Foo *ptr = (Foo *) malloc(sizeof(Foo));
if (ptr == NULL)
return NULL;
new (ptr) Foo;
ptr->i = 0; // ok in C++
ptr->d = 0.0; // ok in C++
return ptr;
}
120
struct Foo
{
int i;
double d;
};
Foo* bar()
{
Foo *ptr = (Foo *) malloc(sizeof(Foo));
if (ptr == NULL)
return NULL;
ptr->i = 0; // ok in C, UB in C++ until C++20
ptr->d = 0.0; // ok in C, UB in C++ until C++20
return ptr;
}
121
Thou shalt not auto, unless thy faith is strong and pure
138
Thou shalt not auto, unless thy faith is strong and pure
Thou shalt not write indexed loops for they are abominations before the Code
139
Thou shalt not auto, unless thy faith is strong and pure
Thou shalt not write indexed loops for they are abominations before the Code
Thou shalt wash thy data thoroughly before releasing it
140
Thou shalt not auto, unless thy faith is strong and pure
Thou shalt not write indexed loops for they are abominations before the Code
Thou shalt wash thy data thoroughly before releasing it
Thou shalt not accept data from strangers for they might be sinful
141
Thou shalt not auto, unless thy faith is strong and pure
Thou shalt not write indexed loops for they are abominations before the Code
Thou shalt wash thy data thoroughly before releasing it
Thou shalt not accept data from strangers for they might be sinful
Thou shalt not copy-paste thy code blocks
142
Thy comparison routines shall be correct or else the Wrath of Code will get thee
143
Thy comparison routines shall be correct or else the Wrath of Code will get thee
Thou shalt check thy nullables for they are sinful
144
Thy comparison routines shall be correct or else the Wrath of Code will get thee
Thou shalt check thy nullables for they are sinful
Thou shalt not push that which can be emplaced
145
Thy comparison routines shall be correct or else the Wrath of Code will get thee
Thou shalt check thy nullables for they are sinful
Thou shalt not push that which can be emplaced
Thou shalt not cook signed values with overflow semantics
146
Thy comparison routines shall be correct or else the Wrath of Code will get thee
Thou shalt check thy nullables for they are sinful
Thou shalt not push that which can be emplaced
Thou shalt not cook signed values with overflow semantics
He who is without noexcept shall throw, and none other
147