In my previous posts, I've given an intro to Cppcheck and also described how to integrate it with CMake.
In this post I'm going to start looking at some of the errors that Cppcheck can help you find in your code.
Memory Leaks
Every C++ developer will have at some point written code which includes a memory leak. With modern C++ we have tools such as std::unique_ptr
and std::shared_ptr
to help with resource allocation, however, when using raw pointers (e.g. in legacy code), using a tool such as Cppcheck can help catch errors. For example:
12345678910111213#include <string>
#include <iostream>
std::string
*
my_to_string(
int
x) {
return
new std::string(to_string(x));
}
void print_ints() {
for
(
int
i
=
0
; i <
10
;
+
+
i) {
std::string
*
tmp
=
my_to_string(i);
std::cout << tmp <<
"\n"
;
}
}
When run against a compiler, this code doesn't produce any warnings or errors, even with the all warnings enabled. However, when run against cppcheck, we can see:
123$ cppcheck
-
-
enable
=
warning leak.cpp
Checking leak.cpp ...
[leak.cpp:
12
]: (error) Memory leak: tmp
Out of Bounds
Out of bounds memory access can cause issues such as a seg fault or leaking of sensitive data. Using C++ check can help to prevent OOB errors from reaching your final release. For example:
12345678910111213141516171819202122232425262728#include <array>
#include <iostream>
const
int
SZ
=
5
;
std::array<
int
, SZ> array_oob() {
std::array<
int
, SZ> arr;
for
(
int
i
=
0
; i <
=
SZ;
+
+
i) {
arr[i]
=
i;
}
return
arr;
}
void carray_oob() {
int
arr[
5
];
for
(
int
i
=
0
; i <
=
SZ;
+
+
i) {
arr[i]
=
i;
}
}
int
from_outside(
int
c) {
std::array<
int
, SZ> arr;
return
arr[c];
}
void use_from_ouside() {
from_outside(
100
);
}
Will produce the following errors when run with Cppcheck:
12345$ cppcheck
-
-
enable
=
warning oob.cpp
Checking oob.cpp ...
[oob.cpp:
9
]: (error) Array
'arr[5]'
accessed at index
5
, which
is
out of bounds.
[oob.cpp:
17
]: (error) Array
'arr[5]'
accessed at index
5
, which
is
out of bounds.
[oob.cpp:
23
]: (error) Array
'arr[5]'
accessed at index
100
, which
is
out of bounds.
Interestingly using Cppcheck v1.85 the following code does not produce any error:
1234567std::vector<
int
> vector_oob() {
std::vector<
int
> arr;
for
(
int
i
=
0
; i <
=
SZ;
+
+
i) {
arr[i]
=
i;
}
return
arr;
}
Use After Move
Cppcheck will detect the incorrect usage of a moved from variable in the following code:
1234567891011121314#include <string>
#include <iostream>
void
(std::string&& to_print) {
std::string moved(std::move(to_print));
std::cout << moved <<
"\n"
;
}
void use_after_move() {
std::string hello
=
"Hello"
;
(std::move(hello));
hello[
0
]
=
'h'
;
std::cout << hello <<
"\n"
;
}
With the following error:
1234$ cppcheck
-
-
enable
=
warning uam.cpp
Checking uam.cpp ...
[uam.cpp:
13
]: (warning) Access of moved variable
'hello'
.
[uam.cpp:
14
]: (warning) Access of moved variable
'hello'
.
No comments:
Post a Comment