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

From Slicer Wiki
Jump to: navigation, search
(4.1 -> Nightly)
 
Tag: 2017 source edit
 
(21 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 +
<noinclude>{{documentation/versioncheck}}</noinclude>
  
−
Here are some tips to narrow down various issues such as crash, or memory leaks
+
{{documentation/banner
−
 
+
| text  = [https://slicer.readthedocs.io/en/latest/user_guide/get_help.html#slicer-application-does-not-start This page has been moved to read-the-docs.]
−
=Disable features=
+
| background-color = 8FBC8F }}
−
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
 
−
* 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</li>
 
−
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();
 
−
</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>
 
−
* <code>vtkSmartPointer<vtkXXX> myXXX; myXXX.TakeReference(this->CreateObjAndCallerOwnsReference())</code>.
 
−
}}
 
−
 
 
−
=Track a crash while accessing already deleted object pointer=
 
−
If the application crashes by accessing an invalid pointer. The goal here is to find when (and why) the pointer is deleted before it is accessed .
 
−
<ol>
 
−
<li>Before the crash, print the value of the pointer:</li>
 
−
Add before the crash (i.e. <code>this->MyObject->update()</code>)
 
−
std::cout << ">>>>>Object pointer: " << this->MyObject << std::endl;
 
−
<li>Add a counter in the destructor:</li>
 
−
Add in the object destructor (it can be in the base class (vtkObject or vtkMRMLNode) if you don't know the type):
 
−
static int count = 0;
 
−
std::cout << "#######Object Destructed: " << this << " " << count++ << std::endl;
 
−
<li>Run the application and make it crash.</li>
 
−
<li>In the logs you shall see something like that:</li>
 
−
#######Object Destructed: 0x12345678 0
 
−
#######Object Destructed: 0x12345679 1
 
−
#######Object Destructed: 0x12345680 2
 
−
>>>>>Object Pointer: 0x12345660
 
−
>>>>>Object Pointer: 0x12345661
 
−
>>>>>Object Pointer: 0x12345662
 
−
#######Object Destructed: 0x12345660 3
 
−
#######Object Destructed: 0x12345661 4
 
−
#######Object Destructed: 0x12345662 5
 
−
#######Object Destructed: 0x12345663 6
 
−
>>>>>Object Pointer: 0x12345670
 
−
>>>>>Object Pointer: 0x12345671
 
−
>>>>>Object Pointer: 0x12345672
 
−
#######Object Destructed: 0x12345660 7
 
−
#######Object Destructed: 0x12345661 8
 
−
#######Object Destructed: 0x12345662 9
 
−
>>>>>Object Pointer: '''0x12345663'''
 
−
Segfault
 
−
<li> Search in the logs when the pointer before crash has been deleted. Set a conditional breakpoint in the debugger:</li>
 
−
(gdb) break MyObj.cxx:103 if count == 6
 
−
or
 
−
(gdb) break MyObj.cxx:103
 
−
(gdb) ignore 1 5
 
−
or if you don't want to use a debugger, you can make it crash the 6th time:
 
−
assert(count != 6);
 
−
<li> Analyze the backtrace to understand why the pointer has been deleted without letting know the object that tries to access it.</li>
 
−
</ol>
 

Latest revision as of 21:02, 12 February 2022

Home < Documentation < Nightly < Developers < Tutorials < Troubleshooting