(non) comprehensive guide to c/c++ source code quality

34
(Non) Comprehensive Guide to C/C++ Source Code Quality Sergey Kishchenko Quickoffice April 1st, 2011 Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code Quality April 1st, 2011 1 / 34

Upload: sergey-kishchenko

Post on 26-Mar-2015

3.005 views

Category:

Documents


0 download

DESCRIPTION

These are slides from my latest talk on C/C++ source code quality at Quickoffice

TRANSCRIPT

Page 1: (Non) Comprehensive Guide to C/C++ Source Code Quality

(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

Page 2: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 3: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 4: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 5: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 6: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 7: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 8: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 9: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 10: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 11: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 12: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 13: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 14: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 15: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 16: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 17: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 18: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 19: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 20: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 21: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 22: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 23: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 24: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 25: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 26: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 27: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 28: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 29: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 30: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 31: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 32: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 33: (Non) Comprehensive Guide to C/C++ Source Code Quality

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

Page 34: (Non) Comprehensive Guide to C/C++ Source Code Quality

Thank you! Questions?

Sergey Kishchenko (Quickoffice) (Non) Comprehensive Guide to C/C++ Source Code QualityApril 1st, 2011 34 / 34