Difference between revisions of "Debugging Inkscape"

From Inkscape Wiki
Jump to navigation Jump to search
Line 47: Line 47:
===Example of how to fix a bug===
===Example of how to fix a bug===
See this bugreport:
See this bugreport:
http://sourceforge.net/tracker/index.php?func=detail&aid=1835591&group_id=93438&atid=604306
https://bugs.launchpad.net/inkscape/+bug/169135


I started gdb like above. And then I saw this:
I started gdb like above. And then I saw this:

Revision as of 20:53, 29 November 2007

  • If you're hunting down a GTK warning, you can set a breakpoint in gdb for "g_logv" so you can capture a backtrace. ("br g_logv", "run", "bt")
  • Bug list

- w32 version asks for (that crappy) Verdana typeface (which is not the most usual w32 typeface, also some users have deleted it to save disk space)

Debugging Tips for Windows

First, have a look at the Using Eclipse page for how to use that program on Windows to debug Inkscape.

Second, make use of the View > Messages... dialog from within the program. Capturing the log here will show you messages printed with g_message(), g_warning(), and g_error()..

Finally, look into how to compile Inkscape as a command line app so you can capture debug messages at the prompt, more like you would do in Linux.

How Johan works

Of course I am always compiling with -mconsole, instead of -mwindows. I don't compile with -g or any other extra flags. This is unnecessary and reduces build times significantly.

For example for crashes, usually I add g_message("blah") to the code to see where the execution of code goes and to see on which line things break:

   g_message("1");
   some_piece_of_code1();
   g_message("2");
   some_piece_of_code2();
   g_message("3");
   some_piece_of_code3();
   g_message("4");
   some_piece_of_code4();
   g_message("5");

If I see the message "2" but not "3" I know the crash happened in some_piece_of_code2.

I also use GDB to get backtraces. Again, don't compile with -g. Not necessary at all! One of the problems with running Inkscape in gdb is that you cannot open a file with the file dialog: Inkscape will hang. I don't know the reason, but I do know a solution! Open the file through Inkscape's cmdline parameters:

    D:\Inkscape\inkscape>gdb
    GNU gdb 6.6
    Copyright (C) 2006 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
    This GDB was configured as "i686-pc-mingw32".
    (gdb) file inkscape.exe inkscape.dbg
    Reading symbols from D:\Inkscape\inkscape/inkscape.exe...(no debugging symbols found)...done.
    Reading symbols from D:\Inkscape\inkscape/inkscape.dbg...done.
    (gdb) run Tekening.svg
    Starting program: D:\Inkscape\inkscape/inkscape.exe Tekening.svg

Example of how to fix a bug

See this bugreport: https://bugs.launchpad.net/inkscape/+bug/169135

I started gdb like above. And then I saw this:

   Program received signal SIGSEGV, Segmentation fault.
   0x005c94ec in Inkscape::UI::Widget::Scalar::setValue ()
   (gdb) bt
   #0  0x005c94ec in Inkscape::UI::Widget::Scalar::setValue ()
   #1  0x0044fc11 in Inkscape::CanvasXYGrid::readRepr ()
   #2  0x0044de22 in Inkscape::CanvasXYGrid::onReprAttrChanged ()

The crashing piece of code looked like this:

  void Scalar::setValue(double value)
  {
      g_assert(_widget != NULL);
      setProgrammatically = true; // callback is supposed to reset back, if it cares
      static_cast<Gtk::SpinButton*>(_widget)->set_value(value);
  }

Nothing much can crash there, the assert checks that _widget is not NULL, and then the cast is valid aswell. So what crashed? What happens is that the setValue method is called for an object that does not exist. _widget is not NULL, but "this" is! this->_widget would crash. g_assert (this != NULL) would give an assertion message. (checked by adding " if (this==NULL) g_message("ja hoor"); " )

It is absurd to check for "this" to be non-NULL at the start of every method, so the bug is not in this method but in the function calling it! That's why we turn our attention to Inkscape::CanvasXYGrid::readRepr ().

readRepr is long, but we only have to look where it does something with a Scalar widget. It's the validateScalar functions. When we comment those out, the bug is solved. (it causes another bug with the specific SVG file, where Inkscape hangs when the grid spacing equals zero. validateScalar used to check for that...) The strange thing is that the widgets are all created and initialized in the constructor of CanvasXYGrid. So perhaps readRepr is being called *during* construction of CanvasXYGrid, while the Scalar widget is still invalid? Using the g_message tip above I found out that the problem code was:

       sutemp = _rsu_sx.getSU();
  g_message("CanvasXYGrid 1");
       sutemp->setDigits(4);
  g_message("CanvasXYGrid 2");

Researching the setDigits path, I could not find a bug. Then it hit me: _rsu_sx is initialized, then readRepr is called, but this is before _rsu_sy is initialized. Then

   void RegisteredScalarUnit::setValue (double val)
   {
       _widget->setValue (val);
   }

is called, but _widget is still NULL, hence the crash. As usual, the fix is easy:

   void RegisteredScalarUnit::setValue (double val)
   {
       if (_widget)
           _widget->setValue (val);
   }

Don't forget to fix the setValue methods of the other Registered widgets!!!

The fix can be seen in SVN revision 16544.