wiki:WikiStart/Troubleshooting/DebuggingTechniques

Version 6 (modified by leifole, 7 years ago) (diff)

typo

Debugging techniques

The following section list some techniques that allow to investigate deeper:

Improve logging and increase the logging level

For Orocos components you can set the Orocos logging level via the enviroment variable ORO_LOGLEVEL to a value from 1 to 6. Where 6 allows the DEBUG messages to be shown.

export ORO_LOGLEVEL=6

For libraries its is recommended to use the base logging. In order to activate you can use the environment variable BASE_LOG_LEVEL. Unset the variable to deactivate logging. Otherwise you can set the logging level for the base logger the following log levels: "DEBUG", "INFO", "WARN", "ERROR", "FATAL"

export BASE_LOG_LEVEL="DEBUG"

If you haven't included any logger into your library use the one provided by base. You find the source in base/types, i.e. if you are using the Rock Macros you will have to link to base-lib (yes, base-lib). If you are not using Rock Macros but only CMake you have to do the following

add_definitions(-DBASE_LOG_NAMESPACE=${PROJECT_NAME})

include(FindPkgConfig)

pkg_check_modules(BASE REQUIRED "base-lib")
include_directories(${BASE_INCLUDE_DIRS})
link_directories(${BASE_LIBRARY_DIRS})

add_library(your_library ...)
target_link_libraries(your_library ... ${BASE_LIBRARIES})

Include the logger in the .cpp files only

#include <base/logging.h>

Then you can either use a printfstyle logging

std::string test = "TEST";
LOG_ERROR("This is a log message: %s", test.c_str());

C/C++ >> gdb (gnu debugger) and ddd

The following steps allow you to perform post mortem analysis once your C/C++ program fails and generates a core dump. Change the pattern of the core dump filename since the default is just core

sudo su
echo "core.%e.%p.%h" > /proc/sys/kernel/core_pattern

Find any additional information on the pattern through 'man core'.

In order to get a core dump, allow the core dump size to be unlimited, i.e. in the active shell:

ulimit -c unlimited

Next time your program crashes you will get a properly (given your pattern) named core dump. Call gdb with it, i.e.

gdb <name-of-your-executable> <core-dump-file>
bt

In certain cases, like when an exception is thrown, no coredump is generated. Often the exceptions don't give information on where they happened. There is a way to find out. However, this method only works if the exception doesn't happen directly on startup. You need to have an interval between startup and error, where you can attach your gdb.

  • start your component/whole system normally
  • find your process id using ps a
  • call gdb <binary> <process-id> to attach yourself to the process
  • do a catch throw in gdb, to tell gdb to catch any exception being thrown
  • cont - continues execution of the process
  • do the things that generate your error, gdb should stop the programm
  • do a bt to see where it comes from

to summarize:

ps a
sudo gdb <binary> <process-id>
catch throw
cont
bt

Valgrind

You can test your libraries directly with valgrind. Note that there are different tools available for valgrind, e.g. memcheck, cachegrind, callgrind, helgrind or massif, while memcheck is the default one applied.

valgrind tools=helgrind <your-executable>

Once you use orocos.rb you can activate valgrind as well.

require orocos
include Orocos
Orocos.initialize

Process.run 'your-deployment', 'valgrind' => true do
 ....
end