Upload
sergey-kishchenko
View
3.006
Download
0
Embed Size (px)
DESCRIPTION
These are slides from my latest talk on C/C++ source code quality at Quickoffice
Citation preview
(Non) Comprehensive Guide to C/C++ Source CodeQuality
Sergey Kishchenko
Quickoffice
April 1st, 2011
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 1 / 34
Product quality and source code quality
Source code Product
You can’t make a good quality product with bad quality blueprint!
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 2 / 34
Software product quality
Conformance to the specification
Completeness
Product documentation
Usability
Source code quality
...
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 3 / 34
Source code quality
Correctness(no ”bugs”!)
Maintainability
Readability
Portability
Low complexity
High code reuse
Efficiency
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 4 / 34
Measuring source code quality
Bugs per line of code
Number of lines of code
Conformance to the code styling guide
Amount of platform-dependent code
Code coverage
Comment density
Program execution time, program size
There is no ”silver bullet” source code quality metric :(You should choose some of the points above and produce your own
integral metric.
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 5 / 34
How to measure and improve source code qualityPart 1. Tools
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 6 / 34
CPD
Copy/Paste detection tool. Improves readability, maintainability, increasescode reuse, reduces resources usage. You can download it athttp://pmd.sourceforge.net/cpd.html
How to use
> java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 \
--files /path/to/cpp/source --language cpp
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 7 / 34
gcc -Wall -ansi -pedantic
I’m serious, it is one of the best tools you can get. Do not underestimateit. Improves correctness and portability.
How to use
> gcc -Wall -ansi -pedantic -c /path/to/source/file.cpp
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 8 / 34
clang(static analizer)
C/C++/ObjC frontend for llvm with static analyzer. Improves correctnessand portability. You can get clang at http://clang.llvm.org/
How to use
> clang --analyze /path/to/source/file.cpp
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 9 / 34
clang-test.cpp
# include <stdio.h>
int main(int argc, char** argv)
{
char* fileName; // not initialized!
if (2 == argc)
{
fileName = argv[1];
}
// using fileName
FILE* f = fopen(fileName, "r");
fclose(f);
}
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 10 / 34
Result
clang-test.cpp:11:15: warning: Pass-by-value argument in
function call is undefined
FILE* f = fopen(fileName, "r");
^ ~~~~~~~~
1 warning generated.
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 11 / 34
Valgrind
Improves correctness, efficiency. You can get valgrind athttp://valgrind.org
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 12 / 34
Valgrind. Memcheck
Memory-management problems detector
Usage
> valgrind --tool=memcheck /path/to/binary
or
> valgrind --leak-check=full /path/to/binary
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 13 / 34
memcheck-test.cpp# include <stdexcept>
# include <iostream>
class BuggyPool
{
public:
BuggyPool(int* data)
{
throw std::runtime_error("Hello from BuggyPool"
"(I was written in tough times)");
}
};
void foo()
{
int* values = new int[1024];
BuggyPool pool(values);
// pool is used somehow
delete [] values;
}
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 14 / 34
memcheck-test.cpp(main function)
int main()
{
try
{
foo();
}
catch(std::runtime_error& err)
{
std::cout<<"ERROR: "<< err.what()<<std::endl;
}
}
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 15 / 34
Result==8076== HEAP SUMMARY:
==8076== in use at exit: 4,096 bytes in 1 blocks
==8076== total heap usage: 3 allocs, 2 frees, 4,263 bytes allocated
==8076==
==8076== 4,096 bytes in 1 blocks are definitely lost in loss record 1 of 1
==8076== at 0x4025F0F: operator new[](unsigned int) (in /usr/lib/...)
==8076== by 0x8048B55: foo() (memcheck-test.cpp:14)
==8076== by 0x8048B8D: main (memcheck-test.cpp:24)
==8076==
==8076== LEAK SUMMARY:
==8076== definitely lost: 4,096 bytes in 1 blocks
==8076== indirectly lost: 0 bytes in 0 blocks
==8076== possibly lost: 0 bytes in 0 blocks
==8076== still reachable: 0 bytes in 0 blocks
==8076== suppressed: 0 bytes in 0 blocks
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 16 / 34
Valgrind. Cachegrind and callgrind
These tools can be used to build callgraphs and profile your program.
Usage
> valgrind --tool=callgrind /path/to/binary
and
> callgrind_annotate [callgrind-out-file [source-files...]]
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 17 / 34
Result (for clang-test.cpp)
Ir
. #include <stdio.h>
.
. int main(int argc, char** argv)
4 {
. char* fileName; // not initialized!
2 if (2 == argc)
. {
. fileName = argv[1];
. }
. // using fileName
5 FILE* f = fopen(fileName, "r");
2,082 => ???:_dl_runtime_resolve (1x)
75,972 => ???:fopen (1x)
3 fclose(f);
10 => ???:fclose (1x)
1,124 => ???:_dl_runtime_resolve (1x)
. }
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 18 / 34
Valgrind. Iogrind, Massif and Helgrind
Valgrind has a lot of tools, but full review of them will take too muchtime. So, you can check:
Iogrind — I/O profiler
Massif — heap profiler
Helgrind — data race conditions detector(in threads)
... (and so on. http://valgrind.org is your friend)
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 19 / 34
cppcheck
Static analysis tool. Improves correctness, readability, efficiency. You canget it at http://cppcheck.sourceforge.net/
cppcheck-test.cpp
int main()
{
int values[10] = { 0 };
values[16] = 16;
}
How to use
> cppcheck --enable=all cppcheck-test.cpp
[cppcheck-test.cpp:3]: (style) Variable ’values’ is assigned a
value that is never used
[cppcheck-test.cpp:4]: (error) Array ’values[10]’ index 16
out of bounds
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 20 / 34
EDoc++
Exception problems detector. Improves correctness. You can get it athttp://edoc.sourceforge.net/
How to use
> start_edoc.sh
> g++ -fedoc-source -c /path/to/source.cpp
> edoc --show-all --format simple /path/to/source.cpp.edc
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 21 / 34
edoc-test.cpp
# include <iostream>
class C1{};
class C2{};
void foo() throw (C1)
{
throw C2();
}
class C
{
public:
~C()
{
foo();
}
};
int main() { C c; }
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 22 / 34
Result
ERROR(ECRASH_SPEC): Exception may propogate through restrictive specifier:
The function: foo() can throw an exception of type:
C2 that is not allowed by its specifier list:
throws(C1)
After changing throw (C1) to throw (C2)
ERROR(EMAIN_EXC): An exception may propogate out the main function. :
The exception:
C2 may propagate out the main function which may
cause a program abort.
WARNING(WDESTR_EXC): An exception may propogate through a destructor. :
Destructor: C::~C(), Exception: C2
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 23 / 34
How to measure and improve source code qualityPart 2. Tests
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 24 / 34
Unit and functional tests
Unit and functional tests improve correctness, maintainability, readabilityand portability. Use them! Some of the unit test frameworks:
CxxTest — http://cxxtest.tigris.org/
Google C++ Testing Framework —http://code.google.com/p/googletest/
Boost Test Library — http://www.boost.org/doc/libs/1_42_0/
libs/test/doc/html/index.html
QtTest —http://doc.qt.nokia.com/latest/qtestlib-tutorial.html
CppUnit — http://cppunit.sourceforge.net
TUT — http://tut-framework.sourceforge.net/
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 25 / 34
Tests coverage: GCOV and gcovr
Just writing tests is not cool enough. Try coverage! It helps withcorrectness.
To use GCOV you should compile with additional flags
> gcc -fprofile-arcs -ftest-coverage /path/to/source.cpp
Then you should run your software/tests and then you can usegcovr(https://software.sandia.gov/trac/fast/wiki/gcovr) toanalyze the results:
Results for cppcheck-test.cpp
----------------------------------------------------------
File Lines Exec Cover Missing
----------------------------------------------------------
/path/to/cppcheck-test.cpp 3 3 100%
----------------------------------------------------------
TOTAL 3 3 100%
----------------------------------------------------------
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 26 / 34
Tests coverage: LCOV
You can use LCOV to generate cool HTML reports on coverage. You canget LCOV at http://ltp.sourceforge.net/coverage/lcov.php
How to use
> lcov --directory /path/to/source/dir --zerocounters
> lcov --directory /path/to/source/dir --capture \
--output-file app.info
> genhtml app.info
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 27 / 34
avalanche
Generates ”extreme” test data. You can get it athttp://code.google.com/p/avalanche/
How to use
> avalanche --filename=/path/to/seed /path/to/binary \
/path/to/seed
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 28 / 34
avalanche-test.cpp
# include <stdio.h>
int main(int argc, char** argv)
{
char input[4];
FILE* fd1 = fopen(argv[1], "r");
fread(input, 1, 4, fd1);
if (!strncmp(input,"bad!",4)) abort();
fclose(fd1);
}
Generated exploit 0 0 file
bad!
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 29 / 34
frama-c
Talk about code quality cannot be complete without mentioningcorrectness provers. It is almost impossible to use them, but you shouldknow what they are. You can get frama-c at http://frama-c.com/
How to use
> frama-c -wp -wp-rte -wp-proof alt-ergo framac-test.c
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 30 / 34
framac-test.c
# pragma SeparationPolicy(none)
/*@requires \valid(p);
requires \valid(q);
assigns *p;
assigns *q;
ensures *p == \old(*q);
ensures *q == \old(*p);
*/
void swap(int* p, int* q)
{
int const save = *p;
*p = *q;
*q = save;
}
int main () {
int p[2] = { 0,1};
int *q = (int *)((char*)q+1);
swap(p,q);
}
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 31 / 34
Result
[kernel] preprocessing with "gcc -C -E -I. framac-test.c"
[kernel] preprocessing with "gcc -C -E -I. framac-test2.c"
[rte] annotating function swap
[wp] [WP:simplified] Goal store_swap_function_assigns : Valid
[wp] [Alt-Ergo] Goal store_swap_assert_4_rte : Valid
[wp] [Alt-Ergo] Goal store_swap_assert_3_rte : Valid
[wp] [Alt-Ergo] Goal store_swap_assert_2_rte : Valid
[wp] [Alt-Ergo] Goal store_swap_assert_1_rte : Valid
[wp] [Alt-Ergo] Goal store_swap_post_1_A : Valid
[wp] [Alt-Ergo] Goal store_swap_post_2_B : Valid
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 32 / 34
General ideas
Code review. Improves correctness, readability, maintainability
Continuous integration and automatic build/test/analyze systems
Source code documentation. Improves readability. Check outdoxygen(http://www.stack.nl/~dimitri/doxygen/) — it’scross-platform and easy to use
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 33 / 34
Thank you! Questions?
Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 34 / 34