|
Packit |
1470ea |
|
|
Packit |
1470ea |
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="tooling" xml:lang="el">
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<info>
|
|
Packit |
1470ea |
<link type="guide" xref="index#general-guidelines"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<credit type="author copyright">
|
|
Packit |
1470ea |
<name>Philip Withnall</name>
|
|
Packit |
1470ea |
<email its:translate="no">philip.withnall@collabora.co.uk</email>
|
|
Packit |
1470ea |
<years>2015</years>
|
|
Packit |
1470ea |
</credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<include xmlns="http://www.w3.org/2001/XInclude" href="cc-by-sa-3-0.xml"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<desc>Using the right tool for various tasks</desc>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Ελληνική μεταφραστική ομάδα GNOME</mal:name>
|
|
Packit |
1470ea |
<mal:email>team@gnome.gr</mal:email>
|
|
Packit |
1470ea |
<mal:years>2016</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Θάνος Τρυφωνίδης</mal:name>
|
|
Packit |
1470ea |
<mal:email>tomtryf@gnome.org</mal:email>
|
|
Packit |
1470ea |
<mal:years>2016</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
</info>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<title>Tooling</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Development tools are much more than just a text editor and a compiler.
|
|
Packit |
1470ea |
Correct use of the right tools can drastically ease debugging and tracking
|
|
Packit |
1470ea |
down of complex problems with memory allocation and system calls, amongst
|
|
Packit |
1470ea |
other things. Some of the most commonly used tools are described below;
|
|
Packit |
1470ea |
other tools exist for more specialized use cases, and should be used when
|
|
Packit |
1470ea |
appropriate.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
An overarching principle to use when developing is to always have as many
|
|
Packit |
1470ea |
debugging options enabled as possible, rather than keeping them disabled
|
|
Packit |
1470ea |
until near release time. By constantly testing code with all available
|
|
Packit |
1470ea |
debug tooling, bugs can be caught early on, before they become ingrained in
|
|
Packit |
1470ea |
code and thus harder to remove.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Practically, this means having all compiler and other tool warnings enabled
|
|
Packit |
1470ea |
and set to fail the build process with an error if they are emitted.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<synopsis>
|
|
Packit |
1470ea |
<title>Σύνοψη</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Compile frequently with a second compiler.
|
|
Packit |
1470ea |
(<link xref="#gcc-and-clang"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Enable a large selection of compiler warnings and make them fatal.
|
|
Packit |
1470ea |
(<link xref="#gcc-and-clang"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Use GDB to debug and step through code. (<link xref="#gdb"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Use Valgrind to analyze memory usage, memory errors, cache and CPU
|
|
Packit |
1470ea |
performance and threading errors. (<link xref="#valgrind"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Use gcov and lcov to analyze unit test coverage.
|
|
Packit |
1470ea |
(<link xref="#gcov-and-lcov"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Use compiler sanitizers to analyze memory, thread and undefined behavior
|
|
Packit |
1470ea |
problems. (<link xref="#sanitizers"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Submit to Coverity as a cronjob and eliminate static analysis errors as
|
|
Packit |
1470ea |
they appear. (<link xref="#coverity"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Use Clang static analyzer and Tartan regularly to eliminate statically
|
|
Packit |
1470ea |
analysable errors locally. (<link xref="#clang-static-analyzer"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
</synopsis>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="gcc-and-clang">
|
|
Packit |
1470ea |
<title>GCC και Clang</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<link href="https://gcc.gnu.org/onlinedocs/gcc/">GCC</link> is the
|
|
Packit |
1470ea |
standard C compiler for Linux. An alternative exists in the form of
|
|
Packit |
1470ea |
<link href="http://clang.llvm.org/docs/UsersManual.html">Clang</link>,
|
|
Packit |
1470ea |
with comparable functionality. Choose one (probably GCC) to use as a main
|
|
Packit |
1470ea |
compiler, but occasionally use the other to compile the code, as the two
|
|
Packit |
1470ea |
detect slightly different sets of errors and warnings in code. Clang also
|
|
Packit |
1470ea |
comes with a static analyzer tool which can be used to detect errors in
|
|
Packit |
1470ea |
code without compiling or running it; see
|
|
Packit |
1470ea |
<link xref="#clang-static-analyzer"/>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Both compilers should be used with as many warning flags enabled as
|
|
Packit |
1470ea |
possible. Although compiler warnings do occasionally provide false
|
|
Packit |
1470ea |
positives, most warnings legitimately point to problems in the code, and
|
|
Packit |
1470ea |
hence should be fixed rather than ignored. A development policy of
|
|
Packit |
1470ea |
enabling all warning flags and also specifying the -Werror
|
|
Packit |
1470ea |
flag (which makes all warnings fatal to compilation) promotes fixing
|
|
Packit |
1470ea |
warnings as soon as they are introduced. This helps code quality. The
|
|
Packit |
1470ea |
alternative of ignoring warnings leads to long debugging sessions to track
|
|
Packit |
1470ea |
down bugs caused by issues which would have been flagged up by the
|
|
Packit |
1470ea |
warnings. Similarly, ignoring warnings until the end of the development
|
|
Packit |
1470ea |
cycle, then spending a block of time enabling and fixing them all wastes
|
|
Packit |
1470ea |
time.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Both GCC and Clang support a wide range of compiler flags, only some of
|
|
Packit |
1470ea |
which are related to modern, multi-purpose code (for example, others are
|
|
Packit |
1470ea |
outdated or architecture-specific). Finding a reasonable set of flags to
|
|
Packit |
1470ea |
enable can be tricky, and hence the
|
|
Packit |
1470ea |
<link href="http://www.gnu.org/software/autoconf-archive/ax_compiler_flags.html">
|
|
Packit |
1470ea |
AX_COMPILER_FLAGS </link> macro exists.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
AX_COMPILER_FLAGS enables a consistent set of compiler
|
|
Packit |
1470ea |
warnings, and also tests that the compiler supports each flag before
|
|
Packit |
1470ea |
enabling it. This accounts for differences in the set of flags supported
|
|
Packit |
1470ea |
by GCC and Clang. To use it, add AX_COMPILER_FLAGS to
|
|
Packit |
1470ea |
<file>configure.ac</file>. If you are using in-tree copies of
|
|
Packit |
1470ea |
autoconf-archive macros, copy
|
|
Packit |
1470ea |
<link href="http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_compiler_flags.m4">
|
|
Packit |
1470ea |
<file>ax_compiler_flags.m4</file></link> to the <file>m4/</file> directory
|
|
Packit |
1470ea |
of your project. Note that it depends on the following autoconf-archive
|
|
Packit |
1470ea |
macros which are GPL-licenced so potentially cannot be copied in-tree.
|
|
Packit |
1470ea |
They may have to remain in autoconf-archive, with that as a build time
|
|
Packit |
1470ea |
dependency of the project:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item>ax_append_compile_flags.m4 </item>
|
|
Packit |
1470ea |
<item>ax_append_flag.m4 </item>
|
|
Packit |
1470ea |
<item>ax_check_compile_flag.m4 </item>
|
|
Packit |
1470ea |
<item>ax_require_defined.m4 </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
AX_COMPILER_FLAGS supports disabling -Werror for
|
|
Packit |
1470ea |
release builds, so that releases may always be built against newer
|
|
Packit |
1470ea |
compilers which have introduced more warnings. Set its third parameter to
|
|
Packit |
1470ea |
‘yes’ for release builds (and only release builds) to enable this
|
|
Packit |
1470ea |
functionality. Development and CI builds should always have
|
|
Packit |
1470ea |
-Werror enabled.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Release builds can be detected using the
|
|
Packit |
1470ea |
<link href="http://www.gnu.org/software/autoconf-archive/ax_is_release.html">AX_IS_RELEASE </link>
|
|
Packit |
1470ea |
macro, the result of which can be passed directly to
|
|
Packit |
1470ea |
AX_COMPILER_FLAGS :
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
AX_IS_RELEASE([git])
|
|
Packit |
1470ea |
AX_COMPILER_FLAGS([WARN_CFLAGS],[WARN_LDFLAGS],[$ax_is_release])
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The choice of release stability policy (the first argument to
|
|
Packit |
1470ea |
AX_IS_RELEASE ) should be made per project, taking the
|
|
Packit |
1470ea |
project’s <link xref="versioning">versioning stability</link> into
|
|
Packit |
1470ea |
account.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="gdb">
|
|
Packit |
1470ea |
<title>GDB</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
GDB is the standard debugger for C on Linux. Its most common uses are for
|
|
Packit |
1470ea |
debugging crashes, and for stepping through code as it executes. A full
|
|
Packit |
1470ea |
tutorial for using GDB is given
|
|
Packit |
1470ea |
<link href="https://sourceware.org/gdb/current/onlinedocs/gdb/">
|
|
Packit |
1470ea |
here</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
To run GDB on a program from within the source tree, use:
|
|
Packit |
1470ea |
<cmd>libtool exec gdb --args ./program-name --some --arguments --here</cmd>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
This is necessary due to libtool wrapping each compiled binary in the
|
|
Packit |
1470ea |
source tree in a shell script which sets up some libtool variables. It is
|
|
Packit |
1470ea |
not necessary for debugging installed executables.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
GDB has many advanced features which can be combined to essentially create
|
|
Packit |
1470ea |
small debugging scripts, triggered by different breakpoints in code.
|
|
Packit |
1470ea |
Sometimes this is a useful approach (for example, for
|
|
Packit |
1470ea |
<link href="https://tecnocode.co.uk/2010/07/12/reference-count-debugging-with-gdb/">
|
|
Packit |
1470ea |
reference count debugging</link>), but sometimes simply using
|
|
Packit |
1470ea |
<link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-debug">
|
|
Packit |
1470ea |
g_debug() </link> to output a debug message is simpler.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="valgrind">
|
|
Packit |
1470ea |
<title>Valgrind</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Valgrind is a suite of tools for instrumenting and profiling programs. Its
|
|
Packit |
1470ea |
most famous tool is <link xref="#memcheck">memcheck</link>, but it has
|
|
Packit |
1470ea |
several other powerful and useful tools too. They are covered separately
|
|
Packit |
1470ea |
in the sections below.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A useful way of running Valgrind is to run a program’s unit test suite
|
|
Packit |
1470ea |
under Valgrind, setting Valgrind to return a status code indicating the
|
|
Packit |
1470ea |
number of errors it encountered. When run as part of
|
|
Packit |
1470ea |
<cmd>make check</cmd>, this will cause the checks to succeed if Valgrind
|
|
Packit |
1470ea |
finds no problems, and fail otherwise. However, running
|
|
Packit |
1470ea |
<cmd>make check</cmd> under Valgrind is not trivial to do on the command
|
|
Packit |
1470ea |
line. A macro,
|
|
Packit |
1470ea |
<link href="http://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html">
|
|
Packit |
1470ea |
AX_VALGRIND_CHECK </link> can be used which adds a new
|
|
Packit |
1470ea |
<cmd>make check-valgrind</cmd> target to automate this. To use it:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<steps>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Copy
|
|
Packit |
1470ea |
<link href="http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_valgrind_check.m4">
|
|
Packit |
1470ea |
<file>ax_valgrind_check.m4</file></link> to the <file>m4/</file>
|
|
Packit |
1470ea |
directory of your project.
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>Προσθέστε το AX_VALGRIND_CHECK στο <file>configure.ac</file>. </item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Add @VALGRIND_CHECK_RULES@ to the <file>Makefile.am</file>
|
|
Packit |
1470ea |
in each directory which contains unit tests.
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
</steps>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
When <cmd>make check-valgrind</cmd> is run, it will save its results in
|
|
Packit |
1470ea |
<file>test-suite-*.log</file>, one log file per tool. Note that you will
|
|
Packit |
1470ea |
need to run it from the directory containing the unit tests.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Valgrind has a way to suppress false positives, by using
|
|
Packit |
1470ea |
<link href="http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress">
|
|
Packit |
1470ea |
suppression files</link>. These list patterns which may match error stack
|
|
Packit |
1470ea |
traces. If a stack trace from an error matches part of a suppression
|
|
Packit |
1470ea |
entry, it is not reported. For various reasons, GLib currently causes a
|
|
Packit |
1470ea |
number of false positives in <link xref="#memcheck">memcheck</link> and
|
|
Packit |
1470ea |
<link xref="#helgrind-and-drd">helgrind and drd</link> which must be
|
|
Packit |
1470ea |
suppressed by default for Valgrind to be useful. For this reason, every
|
|
Packit |
1470ea |
project should use a standard GLib suppression file as well as a project
|
|
Packit |
1470ea |
specific one.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Suppression files are supported by the AX_VALGRIND_CHECK
|
|
Packit |
1470ea |
macro:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
@VALGRIND_CHECK_RULES@
|
|
Packit |
1470ea |
VALGRIND_SUPPRESSIONS_FILES = my-project.supp glib.supp
|
|
Packit |
1470ea |
EXTRA_DIST = $(VALGRIND_SUPPRESSIONS_FILES)
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="memcheck">
|
|
Packit |
1470ea |
<title>memcheck</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
memcheck is a memory usage and allocation analyzer. It detects problems
|
|
Packit |
1470ea |
with memory accesses and modifications of the heap (allocations and
|
|
Packit |
1470ea |
frees). It is a highly robust and mature tool, and its output can be
|
|
Packit |
1470ea |
entirely trusted. If it says there is ‘definitely’ a memory leak, there
|
|
Packit |
1470ea |
is definitely a memory leak which should be fixed. If it says there is
|
|
Packit |
1470ea |
‘potentially’ a memory leak, there may be a leak to be fixed, or it may
|
|
Packit |
1470ea |
be memory allocated at initialization time and used throughout the life
|
|
Packit |
1470ea |
of the program without needing to be freed.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
To run memcheck manually on an installed program, use:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<cmd>valgrind --tool=memcheck --leak-check=full my-program-name</cmd>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Or, if running your program from the source directory, use the following
|
|
Packit |
1470ea |
to avoid running leak checking on the libtool helper scripts:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<cmd>libtool exec valgrind --tool=memcheck --leak-check=full ./my-program-name</cmd>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Valgrind lists each memory problem it detects, along with a short
|
|
Packit |
1470ea |
backtrace (if you’ve compiled your program with debug symbols), allowing
|
|
Packit |
1470ea |
the cause of the memory error to be pinpointed and fixed.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A full tutorial on using memcheck is
|
|
Packit |
1470ea |
<link href="http://valgrind.org/docs/manual/mc-manual.html">here</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="cachegrind-and-kcachegrind">
|
|
Packit |
1470ea |
<title>cachegrind και KCacheGrind</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
cachegrind is a cache performance profiler which can also measure
|
|
Packit |
1470ea |
instruction execution, and hence is very useful for profiling general
|
|
Packit |
1470ea |
performance of a program.
|
|
Packit |
1470ea |
<link href="http://kcachegrind.sourceforge.net/html/Home.html">
|
|
Packit |
1470ea |
KCacheGrind</link> is a useful UI for it which allows visualization and
|
|
Packit |
1470ea |
exploration of the profiling data, and the two tools should rarely be
|
|
Packit |
1470ea |
used separately.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
cachegrind works by simulating the processor’s memory hierarchy, so
|
|
Packit |
1470ea |
there are situations where it is
|
|
Packit |
1470ea |
<link href="http://valgrind.org/docs/manual/cg-manual.html#cg-manual.annopts.accuracy">
|
|
Packit |
1470ea |
not perfectly accurate</link>. However, its results are always
|
|
Packit |
1470ea |
representative enough to be very useful in debugging performance
|
|
Packit |
1470ea |
hotspots.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A full tutorial on using cachegrind is
|
|
Packit |
1470ea |
<link href="http://valgrind.org/docs/manual/cg-manual.html">here</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="helgrind-and-drd">
|
|
Packit |
1470ea |
<title>helgrind και drd</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
helgrind and drd are threading error detectors, checking for race
|
|
Packit |
1470ea |
conditions in memory accesses, and abuses of the
|
|
Packit |
1470ea |
<link href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html">
|
|
Packit |
1470ea |
POSIX pthreads API</link>. They are similar tools, but are implemented
|
|
Packit |
1470ea |
using different techniques, so both should be used.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The kinds of errors detected by helgrind and drd are: data accessed from
|
|
Packit |
1470ea |
multiple threads without consistent locking, changes in lock acquisition
|
|
Packit |
1470ea |
order, freeing a mutex while it is locked, locking a locked mutex,
|
|
Packit |
1470ea |
unlocking an unlocked mutex, and several other errors. Each error, when
|
|
Packit |
1470ea |
detected, is printed to the console in a little report, with a separate
|
|
Packit |
1470ea |
report giving the allocation or spawning details of the mutexes or
|
|
Packit |
1470ea |
threads involved so that their definitions can be found.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
helgrind and drd can produce more false positives than memcheck or
|
|
Packit |
1470ea |
cachegrind, so their output should be studied a little more carefully.
|
|
Packit |
1470ea |
However, threading problems are notoriously elusive even to experienced
|
|
Packit |
1470ea |
programmers, so helgrind and drd errors should not be dismissed lightly.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Full tutorials on using helgrind and drd are
|
|
Packit |
1470ea |
<link href="http://valgrind.org/docs/manual/hg-manual.html">here</link>
|
|
Packit |
1470ea |
and <link href="http://valgrind.org/docs/manual/drd-manual.html">
|
|
Packit |
1470ea |
here</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="sgcheck">
|
|
Packit |
1470ea |
<title>sgcheck</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
sgcheck is an array bounds checker, which detects accesses to arrays
|
|
Packit |
1470ea |
which have overstepped the length of the array. However, it is a very
|
|
Packit |
1470ea |
young tool, still marked as experimental, and hence may produce more
|
|
Packit |
1470ea |
false positives than other tools.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
As it is experimental, sgcheck must be run by passing
|
|
Packit |
1470ea |
<cmd>--tool=exp-sgcheck</cmd> to Valgrind, rather than
|
|
Packit |
1470ea |
<cmd>--tool=sgcheck</cmd>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A full tutorial on using sgcheck is
|
|
Packit |
1470ea |
<link href="http://valgrind.org/docs/manual/sg-manual.html">here</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="gcov-and-lcov">
|
|
Packit |
1470ea |
<title>gcov και lcov</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<link href="https://gcc.gnu.org/onlinedocs/gcc/Gcov.html">gcov</link> is
|
|
Packit |
1470ea |
a profiling tool built into GCC, which instruments code by adding extra
|
|
Packit |
1470ea |
instructions at compile time. When the program is run, this code
|
|
Packit |
1470ea |
generates <file>.gcda</file> and <file>.gcno</file> profiling output
|
|
Packit |
1470ea |
files. These files can be analyzed by the <cmd>lcov</cmd> tool, which
|
|
Packit |
1470ea |
generates visual reports of code coverage at runtime, highlighting lines
|
|
Packit |
1470ea |
of code in the project which are run more than others.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A critical use for this code coverage data collection is when running
|
|
Packit |
1470ea |
the unit tests: if the amount of code covered (for example, which
|
|
Packit |
1470ea |
particular lines were run) by the unit tests is known, it can be used to
|
|
Packit |
1470ea |
guide further expansion of the unit tests. By regularly checking the code
|
|
Packit |
1470ea |
coverage attained by the unit tests, and expanding them towards 100%,
|
|
Packit |
1470ea |
you can be sure that the entire project is being tested. Often it is the
|
|
Packit |
1470ea |
case that a unit test exercises most of the code, but not a particular
|
|
Packit |
1470ea |
control flow path, which then harbours residual bugs.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
lcov supports
|
|
Packit |
1470ea |
<link href="http://en.wikipedia.org/wiki/Code_coverage#Basic_coverage_criteria">
|
|
Packit |
1470ea |
branch coverage measurement</link>, so is not suitable for demonstrating
|
|
Packit |
1470ea |
coverage of safety critical code. It is perfectly suitable for
|
|
Packit |
1470ea |
non-safety critical code.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
As code coverage has to be enabled at both compile time and run time, a
|
|
Packit |
1470ea |
macro is provided to make things simpler. The
|
|
Packit |
1470ea |
<link href="http://www.gnu.org/software/autoconf-archive/ax_code_coverage.html">
|
|
Packit |
1470ea |
AX_CODE_COVERAGE </link> macro adds a
|
|
Packit |
1470ea |
<cmd>make check-code-coverage</cmd> target to the build system, which
|
|
Packit |
1470ea |
runs the unit tests with code coverage enabled, and generates a report
|
|
Packit |
1470ea |
using <cmd>lcov</cmd>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
To add AX_CODE_COVERAGE support to a project:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<steps>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Copy
|
|
Packit |
1470ea |
<link href="http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_code_coverage.m4">
|
|
Packit |
1470ea |
<file>ax_code_coverage.m4</file></link> to the <file>m4/</file>
|
|
Packit |
1470ea |
directory of your project.
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>Προσθέστε AX_CODE_COVERAGE στο <file>configure.ac</file>. </item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Add @CODE_COVERAGE_RULES to the top-level
|
|
Packit |
1470ea |
<file>Makefile.am</file>.
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Add $(CODE_COVERAGE_CFLAGS) to the automake
|
|
Packit |
1470ea |
*_CFLAGS variable for each target you want
|
|
Packit |
1470ea |
coverage for, for example for all libraries but no unit test code. Do
|
|
Packit |
1470ea |
the same for $(CODE_COVERAGE_LDFLAGS) and
|
|
Packit |
1470ea |
*_LDFLAGS .
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
</steps>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Documentation on using gcov and lcov is
|
|
Packit |
1470ea |
<link href="http://ltp.sourceforge.net/coverage/lcov.php">here</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="sanitizers">
|
|
Packit |
1470ea |
<title>Address, Thread and Undefined Behavior Sanitizers</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
GCC and Clang both support several sanitizers: sets of extra code and
|
|
Packit |
1470ea |
checks which can be optionally compiled in to an application and used to
|
|
Packit |
1470ea |
flag various incorrect behaviors at runtime. They are powerful tools, but
|
|
Packit |
1470ea |
have to be enabled specially, recompiling your application to enable and
|
|
Packit |
1470ea |
disable them. They cannot be enabled at the same time as each other, or
|
|
Packit |
1470ea |
used at the same time as <link xref="#valgrind">Valgrind</link>. They are
|
|
Packit |
1470ea |
still young, so have little integration with other tooling.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
All sanitizers are available for both GCC and Clang, accepting the same
|
|
Packit |
1470ea |
set of compiler options.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="address-sanitizer">
|
|
Packit |
1470ea |
<title>Address Sanitizer</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The <link href="https://code.google.com/p/address-sanitizer/">address
|
|
Packit |
1470ea |
sanitizer</link> (‘asan’) detects use-after-free and buffer overflow
|
|
Packit |
1470ea |
bugs in C and C++ programs. A full tutorial on using asan is
|
|
Packit |
1470ea |
<link href="http://clang.llvm.org/docs/AddressSanitizer.html#usage">available
|
|
Packit |
1470ea |
for Clang</link> — the same instructions should work for GCC.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="thread-sanitizer">
|
|
Packit |
1470ea |
<title>Thread Sanitizer</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The <link href="https://code.google.com/p/thread-sanitizer/">thread
|
|
Packit |
1470ea |
sanitizer</link> (‘tsan’) detects data races on memory locations, plus
|
|
Packit |
1470ea |
a variety of invalid uses of POSIX threading APIs. A full tutorial on
|
|
Packit |
1470ea |
using tsan is
|
|
Packit |
1470ea |
<link href="http://clang.llvm.org/docs/ThreadSanitizer.html#usage">available
|
|
Packit |
1470ea |
for Clang</link> — the same instructions should work for GCC.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="undefined-behavior-sanitizer">
|
|
Packit |
1470ea |
<title>Undefined Behavior Sanitizer</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The undefined behavior sanitizer (‘ubsan’) is a collection of smaller
|
|
Packit |
1470ea |
instrumentations which detect various potentially undefined behaviors in
|
|
Packit |
1470ea |
C programs. A set of instructions for enabling ubsan is
|
|
Packit |
1470ea |
<link href="http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation">available
|
|
Packit |
1470ea |
for Clang</link> — the same instructions should work for GCC.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="coverity">
|
|
Packit |
1470ea |
<title>Coverity</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<link href="http://scan.coverity.com/">Coverity</link> is one of the most
|
|
Packit |
1470ea |
popular and biggest commercial static analyzer tools available. However,
|
|
Packit |
1470ea |
it is available to use free for Open Source projects, and any project is
|
|
Packit |
1470ea |
encouraged to <link href="https://scan.coverity.com/users/sign_up">sign
|
|
Packit |
1470ea |
up</link>.
|
|
Packit |
1470ea |
<link href="https://scan.coverity.com/faq#how-get-project-included-in-scan">
|
|
Packit |
1470ea |
Analysis is performed</link> by running some analysis tools locally, then
|
|
Packit |
1470ea |
uploading the source code and results as a tarball to Coverity’s site. The
|
|
Packit |
1470ea |
results are then visible online to members of the project, as annotations
|
|
Packit |
1470ea |
on the project’s source code (similarly to how lcov presents its results).
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
As Coverity cannot be run entirely locally, it cannot be integrated
|
|
Packit |
1470ea |
properly into the build system. However, scripts do exist to automatically
|
|
Packit |
1470ea |
scan a project and upload the tarball to Coverity regularly. The
|
|
Packit |
1470ea |
recommended approach is to run these scripts regularly on a server
|
|
Packit |
1470ea |
(typically as a cronjob), using a clean checkout of the project’s git
|
|
Packit |
1470ea |
repository. Coverity automatically e-mails project members about new
|
|
Packit |
1470ea |
static analysis problems it finds, so the same approach as for
|
|
Packit |
1470ea |
<link xref="#gcc-and-clang">compiler warnings</link> can be taken:
|
|
Packit |
1470ea |
eliminate all the static analysis warnings, then eliminate new ones as
|
|
Packit |
1470ea |
they are detected.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Coverity is good, but it is not perfect, and it does produce a number of
|
|
Packit |
1470ea |
false positives. These should be marked as ignored in the online
|
|
Packit |
1470ea |
interface.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="clang-static-analyzer">
|
|
Packit |
1470ea |
<title>Clang Static Analyzer</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
One tool which can be used to perform static analysis locally is the
|
|
Packit |
1470ea |
<link href="http://clang-analyzer.llvm.org/">Clang static analyzer</link>,
|
|
Packit |
1470ea |
which is a tool co-developed with the <link xref="#gcc-and-clang">Clang
|
|
Packit |
1470ea |
compiler</link>. It detects a variety of problems in C code which
|
|
Packit |
1470ea |
compilers cannot, and which would otherwise only be detectable at run time
|
|
Packit |
1470ea |
(using unit tests).
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Clang produces some false positives, and there is no easy way to ignore
|
|
Packit |
1470ea |
them. The recommended thing to do is to
|
|
Packit |
1470ea |
<link href="http://clang-analyzer.llvm.org/faq.html#suppress_issue">file
|
|
Packit |
1470ea |
a bug report against the static analyzer</link>, so that the false
|
|
Packit |
1470ea |
positive can be fixed in future.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A full tutorial on using Clang is
|
|
Packit |
1470ea |
<link href="http://clang-analyzer.llvm.org/scan-build.html">here</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="tartan">
|
|
Packit |
1470ea |
<title>Tartan</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
However, for all the power of the Clang static analyzer, it cannot
|
|
Packit |
1470ea |
detect problems with specific libraries, such as GLib. This is a problem
|
|
Packit |
1470ea |
if a project uses GLib exclusively, and rarely uses POSIX APIs (which
|
|
Packit |
1470ea |
Clang does understand). There is a plugin available for the Clang static
|
|
Packit |
1470ea |
analyzer, called
|
|
Packit |
1470ea |
<link href="http://people.collabora.com/~pwith/tartan/">Tartan</link>,
|
|
Packit |
1470ea |
which extends Clang to support checks against some of the common GLib
|
|
Packit |
1470ea |
APIs.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Tartan is still young software, and will produce false positives and may
|
|
Packit |
1470ea |
crash when run on some code. However, it can find legitimate bugs quite
|
|
Packit |
1470ea |
quickly, and is worth running over a code base frequently to detect new
|
|
Packit |
1470ea |
errors in the use of GLib in the code. Please
|
|
Packit |
1470ea |
<link href="http://people.collabora.com/~pwith/tartan/#troubleshooting">
|
|
Packit |
1470ea |
report any problems with Tartan</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A full tutorial on enabling Tartan for use with the Clang static
|
|
Packit |
1470ea |
analyzer is
|
|
Packit |
1470ea |
<link href="http://people.collabora.com/~pwith/tartan/#usage-standalone">
|
|
Packit |
1470ea |
here</link>. If set up correctly, the output from Tartan will be mixed
|
|
Packit |
1470ea |
together with the normal static analyzer output.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</page>
|