Valgrind¶
Valgrind can be used to detect memory errors that a debugger such as gdb would not otherwise find.
Starting Blender¶
Install valgrind on your system.
macOS¶
http://blog.loudhush.ro/2010/02/compiling-valgrind-on-snow-leopard.html
Linux¶
On ubuntu/debian
Now you can go to the place you built blender and type...
This will run blender in valgrind and generate errors that you can use to find bugs before they crash blender or errors that may cause unpredictable behavior.
These options give more useful output but make blender run slower too.
Example Output¶
==7847== Conditional jump or move depends on uninitialised value(s)
==7847== at 0xC1A2CC: which_vfont (font.c:429)
==7847== by 0xC1B476: BKE_text_to_curve (font.c:774)
==7847== by 0xC4A3C2: do_makeDispListCurveTypes (displist.c:1692)
==7847== by 0xC4AD04: makeDispListCurveTypes_forRender (displist.c:1870)
==7847== by 0xA06554: init_render_curve (convertblender.c:2789)
==7847== by 0xA0CAA9: init_render_object_data (convertblender.c:4392)
==7847== by 0xA0CD65: add_render_object (convertblender.c:4441)
==7847== by 0xA0D099: init_render_object (convertblender.c:4494)
==7847== by 0xA0E3EF: database_init_objects (convertblender.c:4867)
==7847== by 0xA0E923: RE_Database_FromScene (convertblender.c:4955)
==7847== by 0xA7E0D1: do_render_3d (pipeline.c:1773)
==7847== by 0xA7F001: do_render_fields_blur_3d (pipeline.c:2080)
==7847== Uninitialised value was created by a heap allocation
==7847== at 0x4C25FAD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7847== by 0xE0F66B: MEM_mallocN (mallocn.c:308)
==7847== by 0xD0B620: read_struct (readfile.c:1284)
==7847== by 0xD193D6: read_data_into_oldnewmap (readfile.c:5395)
==7847== by 0xD195E5: read_libblock (readfile.c:5453)
==7847== by 0xD2DDF9: blo_read_file_internal (readfile.c:11249)
==7847== by 0xD32CA8: BLO_read_from_file (readblenentry.c:252)
==7847== by 0xC64399: BKE_read_file (blender.c:376)
==7847== by 0x6F21C6: load_file (creator.c:880)
==7847== by 0xD41164: BLI_argsParse (BLI_args.c:276)
==7847== by 0x6F2B6A: main (creator.c:1136)
Analyzing Output¶
There are a few things to consider when reading the output,
- un-initialized memory may be caused by external libraries, unless these libraries are compiled with debug symbols there wont be as useful info. This cases are easy enough to identify, its just good to be mindful that not all reports are caused by issues in blender.
- Reports about un-initialized stack variables will show up at the function beginning even if the variable is defined within a block of the code.
False Positives¶
Valgrind tends to give errors with blender on startup which you can safely ignore.
- X11: Anything related to X11/Xlib.
- Anything relating to drivers (sound, video).
- OpenGL: The OpenGL driver.
- Python: Python uses its own allocator which valgrind detects errors in. (can be resolved with a custom Python build - see below)
- SDL/Sound:
- Blenders Undo System: Uses memory comparison which causes errors.
The kinds of errors you get also depend on how valgrind is installed, since some installations come with default suppression files.
As stated, these happen most when starting blender, so be prepared to ignore many errors on startup.
Compiler Options¶
Another source of false positives can stem from the options used when compiling blender. While not essential starting out. if you are spending a long time to track a bug down its better to be sure its reported correctly.
- Compile with debug enabled
- Disable optimizations
- Disable in-lining
For gcc these flags are: -O0 -g3 -fno-inline
Python Compiler Options¶
As mentioned before, python can be the cause of many false positives.
This can be avoided by building python without its own malloc replacement '--without-pymalloc' and will quiet most false positives.
Example of building python with debug options and without pymalloc.
CFLAGS="-fno-inline -g3 -O0" ./configure --prefix=/opt/py33 --enable-shared --with-pydebug --without-pymalloc --with-valgrind
make
make install
If you really don't need python, you can also disable the build option
WITH_PYTHON
but this will remove most of the user interface.
Debugging¶
This requires using gdbserver and isn't essential for valgrind to be useful.
See: http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver-gdb
Error Suppression¶
*Note*. setting suppressions is not strictly necessary but if you run valgrind a lot you may want to set it up - trying to find useful errors in thousands of reports is not really fun.
If you try running the command above you'll see meny errors, most of which are not useful. to address this you need to make a suppressions file.
Generic Suppressions¶
Note: heavily based on http://stackoverflow.com/questions/2375726/how-do-you-tell-valgrind-to-completely-suppress-a-particular-so-file.
We said above that we could ignore Python, OpenGL driver, etc. errors.
You can tell valgrind to silently do that by using its --suppressions
option and a text file defining ignore rules.
The general format is basically:
# A line starting with a '#' is a comment.
# Start of a rule
{
# Name of the rule, you can use what you want here...
Foobar
# Memcheck specifies the type of error this rule will "silent".
Memcheck:Cond
# Then we have an optional stack of object files (i.e. libraries).
# You should use the full lib paths.
# The '...' are "frame wildcards", they say this rule is valid
# for any object file before and after libpython.
...
obj:/usr/lib/x86_64-linux-gnu/libpython3.3m.so.1.0
...
# Then we have an optional stack of function calls.
# Here again, the '...' are "frame wildcards", for functions this time.
...
fun:gpu_buffer_setup
fun:gpu_buffer_setup_type
fun:gpu_buffer_setup_common
...
# Close the rule
}
Refining¶
Above file (once adapted to your system) should cover nearly all false positives. However, you may want to add more specific rules. In this case, use the following method:
valgrind --suppressions=~/blender_sup.txt --gen-suppressions=all ./blender 2> ~/blender_sup_TEMP.txt
This will add suppression rules to ~/blender_sup_TEMP.txt
for all
errors not already covered by your current ~/blender_sup.txt
file.
Open blender and do some operations generating the errors you want to
get rid of…
Open ~/blender_sup_TEMP.txt
, select the errors you want to ignore, and
copy their content between the braces {...}
into your
~/blender_sup.txt
file. You should also add some comments about
what/why you add those rules.
Now you can can use valgrind as usual (using the
--suppressions=~/blender_sup.txt
option), just keep in mind you
disabled a bunch of errors, in case you can’t find what you are looking
for!
Some errors may keep appearing and you can ignore them:
- Undo - blender compares un-initialized memory when running undo, you cant supress this from 1 place because undo is called in many areas.
- Python - Python does its own memory management which confuses valgrind, and is also called in many places.