Difference between revisions of "Documentation/4.0/Developers/Tutorials/Troubleshooting"

From Slicer Wiki
Jump to: navigation, search
Line 1: Line 1:
 
{{documentation/underconstruction}}
 
{{documentation/underconstruction}}
 +
Here are some tips to narrow down various issues such as crash, or memory leaks
  
* Disable plugins
+
=Disable features=
 +
Try running Slicer with as few features as possible:
 +
* Disable Slicer options via the command line
 +
*: <pre>$ ./Slicer --no-splash --ignore-slicerrc --disable-cli-module --disable-loadable-module --disable-scriptedmodule</pre>
 +
** Look at all the possible options
 +
**: <pre>$ ./Slicer --help</pre>
 +
* Disable ITK plugins
 +
*: CLI modules silently load the ITK plugins in lib/Slicer-4.0/ITKFactories. These plugins are used to share the volumes between Slicer and the ITK filter without having to copy them on disk.
 
** rename lib/Slicer-4.0/ITKFactories into lib/Slicer-4.0/ITKFactories-disabled
 
** rename lib/Slicer-4.0/ITKFactories into lib/Slicer-4.0/ITKFactories-disabled
 +
* Disable Qt plugins
 +
** rename lib/Slicer-4.0/iconengine into lib/Slicer-4.0/iconengine-disabled
 +
 +
=Track memory leaks=
 +
<ol>
 +
<li> Turn ON the VTK_DEBUG_LEAKS CMake variable and build Slicer</li>
 +
<li> Create a test that reproduces the memory leak systematically </li>
 +
After execution, the memory leaks are printed automatically by VTK on the standard output:
 +
224: vtkDebugLeaks has detected LEAKS!
 +
224: Class "vtkProperty2D" has 60 instances still around.
 +
...
 +
<li>Find what specific instance of a class (here vtkProperty2D) leaks.</li>
 +
If the class is instantiated a large amount of time, it is hard to know what instance is leaking.
 +
You can edit the constructor and destructor of the class (here vtkProperty2D::vtkProperty2D() and vtkProperty2D::~vtkProperty2D())
 +
vtkProperty2D::vtkProperty2D()
 +
{
 +
...
 +
static int count = 0;
 +
std::cout << "CREATE vtkProperty2D instance #" << count++ << " " << this << std::endl;
 +
}
 +
 +
vtkProperty2D::~vtkProperty2D()
 +
{
 +
...
 +
static int count = 0;
 +
std::cout << "DELETE vtkProperty2D instance #" << count++ << " " << this << std::endl;
 +
}
 +
Don't forget to rebuild VTK if the class is from VTK (and not just Slicer inner build)
 +
After running the test again, you should see a list of
 +
...
 +
CREATE vtkProperty2D instance #0 0x0123456
 +
...
 +
CREATE vtkProperty2D instance #1 0x01234E5
 +
...
 +
DELETE vtkProperty2D instance #0 0x0123456
 +
...
 +
DELETE vtkProperty2D instance #1 0x01234E5
 +
...
 +
CREATE vtkProperty2D instance #2 0x0123A23
 +
...
 +
CREATE vtkProperty2D instance #3 0x0124312
 +
...
 +
Copy/paste the listing in a text editor and ensure that for each CREATE of a pointer (e.g. 0x0123456) it exists a DELETE. If there isn't, you found what instance is leaking. Note the instance # (here instance #2 and #3)
 +
Run the test with the [[Documentation/4.0/Developers/Tutorials/Debug_Instructions debugger]], set a breakpoint in the class constructor and ignore the break as many time as the instance number:
 +
(gdb) break vtkProperty2D::vtkProperty2D()
 +
Breakpoint 1 at 0x5b22d0e55d04296: file vtkProperty2D.cxx, line 22
 +
(gdb) ignore 1 2
 +
When the debugger stops, check the call stack:
 +
(gdb) backtrace
 +
By analyzing the trace, you should be able to find the faulty instance.
 +
</li>
 +
<li> Analyze the code to see where the leak could be
 +
Here is a listing of the most common mistakes
 +
* this->MyXXX = vtkXXX::New();
 +
** Is there a matching this->MyXXX->Delete() ?
 +
** Are you sure <code>this->MyXXX</code> is <code>0</code> before being assigned a new pointer ?  If not, then you need to add
 +
if (this->MyXXX != 0)
 +
  {
 +
  this->MyXXX->Delete();
 +
  this->MyXXX = 0;
 +
  }
 +
  this->MyXXX = vtkXXX::New();
 +
</li>
 +
</ol>
 +
{{ombox
 +
|type=content
 +
|text=To reduce memory leaks, use the following tools:
 +
* <code>vtkNew<vtkXXX> myXXX;</code>,
 +
* <code>vtkSmartPointer<vtkXXX> myXXX = vtkSmartPointer<vtkXXX>::New()</code>
 +
* and <code>vtkSmartPointer<vtkXXX> myXXX; myXXX.TakeReference(this->CreateObjAndCallerOwnsReference())</code>.
 +
}}

Revision as of 21:36, 27 December 2011

Home < Documentation < 4.0 < Developers < Tutorials < Troubleshooting


Here are some tips to narrow down various issues such as crash, or memory leaks

Disable features

Try running Slicer with as few features as possible:

  • Disable Slicer options via the command line
    $ ./Slicer --no-splash --ignore-slicerrc --disable-cli-module --disable-loadable-module --disable-scriptedmodule
    • Look at all the possible options
      $ ./Slicer --help
  • Disable ITK plugins
    CLI modules silently load the ITK plugins in lib/Slicer-4.0/ITKFactories. These plugins are used to share the volumes between Slicer and the ITK filter without having to copy them on disk.
    • rename lib/Slicer-4.0/ITKFactories into lib/Slicer-4.0/ITKFactories-disabled
  • Disable Qt plugins
    • rename lib/Slicer-4.0/iconengine into lib/Slicer-4.0/iconengine-disabled

Track memory leaks

  1. Turn ON the VTK_DEBUG_LEAKS CMake variable and build Slicer
  2. Create a test that reproduces the memory leak systematically
  3. After execution, the memory leaks are printed automatically by VTK on the standard output: 224: vtkDebugLeaks has detected LEAKS! 224: Class "vtkProperty2D" has 60 instances still around. ...
  4. Find what specific instance of a class (here vtkProperty2D) leaks.
  5. If the class is instantiated a large amount of time, it is hard to know what instance is leaking. You can edit the constructor and destructor of the class (here vtkProperty2D::vtkProperty2D() and vtkProperty2D::~vtkProperty2D()) vtkProperty2D::vtkProperty2D() { ... static int count = 0; std::cout << "CREATE vtkProperty2D instance #" << count++ << " " << this << std::endl; } vtkProperty2D::~vtkProperty2D() { ... static int count = 0; std::cout << "DELETE vtkProperty2D instance #" << count++ << " " << this << std::endl; } Don't forget to rebuild VTK if the class is from VTK (and not just Slicer inner build) After running the test again, you should see a list of ... CREATE vtkProperty2D instance #0 0x0123456 ... CREATE vtkProperty2D instance #1 0x01234E5 ... DELETE vtkProperty2D instance #0 0x0123456 ... DELETE vtkProperty2D instance #1 0x01234E5 ... CREATE vtkProperty2D instance #2 0x0123A23 ... CREATE vtkProperty2D instance #3 0x0124312 ... Copy/paste the listing in a text editor and ensure that for each CREATE of a pointer (e.g. 0x0123456) it exists a DELETE. If there isn't, you found what instance is leaking. Note the instance # (here instance #2 and #3) Run the test with the Documentation/4.0/Developers/Tutorials/Debug_Instructions debugger, set a breakpoint in the class constructor and ignore the break as many time as the instance number: (gdb) break vtkProperty2D::vtkProperty2D() Breakpoint 1 at 0x5b22d0e55d04296: file vtkProperty2D.cxx, line 22 (gdb) ignore 1 2 When the debugger stops, check the call stack: (gdb) backtrace By analyzing the trace, you should be able to find the faulty instance.
  6. Analyze the code to see where the leak could be Here is a listing of the most common mistakes
    • this->MyXXX = vtkXXX::New();
      • Is there a matching this->MyXXX->Delete() ?
      • Are you sure this->MyXXX is 0 before being assigned a new pointer ? If not, then you need to add
    if (this->MyXXX != 0) { this->MyXXX->Delete(); this->MyXXX = 0; } this->MyXXX = vtkXXX::New();