I am trying to write a GTK application and want to test its validity with valgrind.
This is an example program I want to test:
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
int
main (int argc, char *argv[])
{
GtkWidget *win;
GtkWidget *btn;
gtk_init (&argc, &argv);
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
btn = gtk_button_new_with_label ("Hello");
gtk_container_add (GTK_CONTAINER (win), btn);
gtk_widget_show_all (win);
gtk_main();
}
The GNOME Foundation wrote a an article about testing applications with valgrind, but even if I start valgrind with all this flags
valgrind --tool=memcheck --leak-check=full --num-callers=15 --log-file=vgdump ./diashow
or even with the gtk.suppression file mentioned on that valgrind-page
valgrind --tool=memcheck --leak-check=full --num-callers=15 --suppressions=gtk.suppression --log-file=vgdump ./diasho
the valgrind dumpfile (pastebin) vgdump
is quite unreadable. 2285 lines!
The weirdest part for me is that my vgdump-file starts with Invalid write of size 4
and then Invalid read of size 4
. Can someone explain anything of that to me?
In my experience a good rule when working with valgrind is to check a few errors at the beginning, try to fix these, and restart an app under valgrind again. The reason is: suppose you have an error in a function that allocates an array, and calls another function with the array and the size of the array+1 (i.e. the size one element more of the real size). Then when the next function would try to access that excessive element, valgrind may notice it and trigger a warning. But the function may call another function, which may also try to access the element as well, which also leads to the warning, and so on.
So you end up with a bunch of messages that leads to a single error. And even if there's messages about another error, find these would usually be so hard, that it is easier to fix the first error, and restart app and valgrind again.
Also you need to take valgrind errors with a bit of skepticism. E.g. I remember it once reported to me about an uninitialized variable in a function main — for some reason valgrind couldn't see it actually is. It led to a message about an uninitialized variable usage in every function that main calls — i.e. every function in my program. But I should mention that it was long ago — three years ago — and I can suppose that the valgrind wasn't a recent version even back then just because Ubuntu repository tends to not have a latest versions of many apps.
The
Invalid read of size 4
means a buffer overflow somewhere. The stacktrace of the first such error should point where you could find the problem. It is hard to say more as you didn't show the stacktrace, but you have to know that the function with the error may be a victim of a wrong array from above.As an aside note I'd advice you to debug that kind of errors with AddressSanitizer which is available for both GCC and Clang by default (and they have the same options to enable it). It tends to give a much more verbose output about an error (yay, it is even colorful! ε:), and by default closes an app when any kind of memory error occurred. More over, valgrind misses most of memory errors when AddressSanitizer doesn't — such as stack overflows, and etc. Yes, sometimes (as in your case) it works, but from my experience aren't very often.