0027447: Add support for long IGES entity names
[occt.git] / dox / dev_guides / debug / debug.md
CommitLineData
ba06f8bb 1Debugging tools and hints {#occt_dev_guides__debug}
d4faf9e9 2=========================
3
4@tableofcontents
5
21087d91 6@section occt_debug_intro Introduction
7
8This manual describes facilities included in OCCT to support debugging, and provides some hints for more efficient debug.
9
0797d9d3 10@section occt_debug_macro Compiler macro to enable extended debug messages
11
12Many OCCT algorithms can produce extended debug messages, usually printed to cout.
13These include messages on internal errors and special cases encountered, timing etc.
14In OCCT versions prior to 6.8.0 most of these messages were activated by compiler macro *DEB*, enabled by default in debug builds.
15Since version 6.8.0 this is disabled by default but can be enabled by defining compiler macro *OCCT_DEBUG*.
16
17To enable this macro on Windows when building with Visual Studio projects, edit file custom.bat and add the line:
18
19 set CSF_DEFINES=OCCT_DEBUG
20
21Some algorithms use specific macros for yet more verbose messages, usually started with OCCT_DEBUG_.
22These messages can be enabled in the same way, by defining corresponding macro.
23
24Note that some header files are modified when *OCCT_DEBUG* is enabled, hence binaries built with it enabled are not compatible with client code built without this option; this is not intended for production use.
25
26@section occt_debug_exceptions Calling JIT debugger on exception
27
28On Windows platform when using Visual Studio compiler there is a possibility to start the debugger automatically if an exception is caught in a program running OCCT. For this, set environment variable *CSF_DEBUG* to any value. Note that this feature works only if you enable OCCT exception handler in your application by calling *OSD::SetSignal()*.
29
d4faf9e9 30@section occt_debug_bop Self-diagnostics in Boolean operations algorithm
31
32In real-world applications modeling operations are often performed in a long sequence, while the user sees only the final result of the whole sequence. If the final result is wrong, the first debug step is to identify the offending operation to be debugged further. Boolean operation algorithm in OCCT provides a self-diagnostic feature which can help to do that step.
33
34This feature can be activated by defining environment variable *CSF_DEBUG_BOP*, which should specify an existing writeable directory.
35
36The diagnostic code checks validity of the input arguments and the result of each Boolean operation. When an invalid situation is detected, the report consisting of argument shapes and a DRAW script to reproduce the problematic operation is saved to the directory pointed by *CSF_DEBUG_BOP*.
37
d4faf9e9 38@section occt_debug_call Functions for calling from debugger
39
40Modern interactive debuggers provide the possibility to execute application code at a program break point. This feature can be used to analyse the temporary objects available only in the context of the debugged code. OCCT provides several global functions that can be used in this way.
41
42Note that all these functions accept pointer to variable as <i>void*</i> to allow calling the function even when debugger does not recognize type equivalence or can not perform necessary type cast automatically. It is responsibility of the developer to provide the correct pointer. In general these functions are not guaranteed to work, thus use them with caution and at your own risk.
43
44@subsection occt_debug_call_draw Interacting with DRAW
45
ba06f8bb 46Open CASCADE Test Harness or @ref occt_user_guides__test_harness "DRAW" provides an extensive set of tools for inspection and analysis of OCCT shapes and geometric objects and is mostly used as environment for prototyping and debugging OCCT-based algorithms.
d4faf9e9 47
48In some cases the objects to be inspected are available in DRAW as results of DRAW commands. In other cases, however, it is necessary to inspect intermediate objects created by the debugged algorithm. To support this, DRAW provides a set of commands allowing the developer to store intermediate objects directly from the debugger stopped at some point during the program execution (usually at a breakpoint).
49
50~~~~~
51const char* Draw_Eval (const char *theCommandStr)
52~~~~~
53
54Evaluates a DRAW command or script.
55A command is passed as a string parameter.
56
57~~~~~
58const char* DBRep_Set (const char* theNameStr, void* theShapePtr)
59~~~~~
60
61Sets the specified shape as a value of DRAW interpreter variable with the given name.
3f812249 62- *theNameStr* -- the DRAW interpreter variable name to set.
63- *theShapePtr* -- a pointer to *TopoDS_Shape* variable.
d4faf9e9 64
66d914e8 65~~~~~
66const char* DBRep_SetComp (const char* theNameStr, void* theListPtr)
67~~~~~
68
69Makes a compound from the specified list of shapes and sets it as a value of DRAW interpreter variable with the given name.
70- *theNameStr* -- the DRAW interpreter variable name to set.
71- *theListPtr* -- a pointer to *TopTools_ListOfShape* variable.
72
d4faf9e9 73~~~~~
74const char* DrawTrSurf_Set (const char* theNameStr, void* theHandlePtr)
75const char* DrawTrSurf_SetPnt (const char* theNameStr, void* thePntPtr)
76const char* DrawTrSurf_SetPnt2d (const char* theNameStr, void* thePnt2dPtr)
77~~~~~
78
79Sets the specified geometric object as a value of DRAW interpreter variable with the given name.
3f812249 80- *theNameStr* -- the DRAW interpreter variable name to set.
81- *theHandlePtr* -- a pointer to the geometric variable (Handle to *Geom_Geometry* or *Geom2d_Curve* or descendant) to be set.
82- *thePntPtr* -- a pointer to the variable of type *gp_Pnt* to be set.
83- *thePnt2dPtr* -- a pointer to the variable of type *gp_Pnt2d* to be set.
d4faf9e9 84
85All these functions are defined in *TKDraw* toolkit and return a string indicating the result of execution.
86
87@subsection occt_debug_call_brep Saving and dumping shapes and geometric objects
88
89The following functions are provided by *TKBRep* toolkit and can be used from debugger prompt:
90
91~~~~~
92const char* BRepTools_Write (const char* theFileNameStr, void* theShapePtr)
93~~~~~
94
95Saves the specified shape to a file with the given name.
3f812249 96- *theFileNameStr* -- the name of the file where the shape is saved.
97- *theShapePtr* -- a pointer to *TopoDS_Shape* variable.
d4faf9e9 98
99~~~~~
100const char* BRepTools_Dump (void* theShapePtr)
101const char* BRepTools_DumpLoc (void* theShapePtr)
102~~~~~
103
104Dumps shape or its location to cout.
3f812249 105- *theShapePtr* -- a pointer to *TopoDS_Shape* variable.
d4faf9e9 106
fc9b36d6 107The following function is provided by *TKMesh* toolkit:
108
109~~~~~
110const char* BRepMesh_Dump (void* theMeshHandlePtr, const char* theFileNameStr)
111~~~~~
112
113Stores mesh produced in parametric space to BREP file.
3f812249 114- *theMeshHandlePtr* -- a pointer to *Handle(BRepMesh_DataStructureOfDelaun)* variable.
115- *theFileNameStr* -- the name of the file where the mesh is stored.
fc9b36d6 116
d4faf9e9 117The following additional function is provided by *TKGeomBase* toolkit:
118
119~~~~~
120const char* GeomTools_Dump (void* theHandlePtr)
121~~~~~
122
123Dump geometric object to cout.
3f812249 124- *theHandlePtr* -- a pointer to the geometric variable (<i>Handle</i> to *Geom_Geometry* or *Geom2d_Curve* or descendant) to be set.
d4faf9e9 125
126@section occt_debug_vstudio Using Visual Studio debugger
127
128@subsection occt_debug_vstudio_command Command window
129
130Visual Studio debugger provides the Command Window (can be activated from menu <b>View / Other Windows / Command Window</b>), which can be used to evaluate variables and expressions interactively in a debug session (see http://msdn.microsoft.com/en-us/library/c785s0kz.aspx). Note that the Immediate Window can also be used but it has some limitations, e.g. does not support aliases.
131
132When the execution is interrupted by a breakpoint, you can use this window to call the above described functions in context of the currently debugged function. Note that in most cases you will need to specify explicitly context of the function by indicating the name of the DLL where it is defined.
133
134For example, assume that you are debugging a function, where local variable *TopoDS_Edge* *anEdge1* is of interest.
135The following set of commands in the Command window will save this edge to file *edge1.brep*, then put it to DRAW variable *e1* and show it maximized in the axonometric DRAW view:
136
137~~~~~
138>? ({,,TKBRep.dll}BRepTools_Write)("d:/edge1.brep",(void*)&anEdge1)
1390x04a2f234 "d:/edge1.brep"
140>? ({,,TKDraw.dll}DBRep_Set)("e1",(void*)&anEdge1)
1410x0369eba8 "e1"
142>? ({,,TKDraw.dll}Draw_Eval)("donly e1; axo; fit")
1430x029a48f0 ""
144~~~~~
145
146For convenience it is possible to define aliases to commands in this window, for instance (here ">" is prompt provided by the command window; in the Immediate window this symbol should be entered manually):
147
148~~~~~
149>alias deval ? ({,,TKDraw}Draw_Eval)
150>alias dsetshape ? ({,,TKDraw}DBRep_Set)
66d914e8 151>alias dsetcomp ? ({,,TKDraw}DBRep_SetComp)
e3e895af 152>alias dsetgeom ? ({,,TKDraw}DrawTrSurf_Set)
153>alias dsetpnt ? ({,,TKDraw}DrawTrSurf_SetPnt)
d4faf9e9 154>alias dsetpnt2d ? ({,,TKDraw}DrawTrSurf_SetPnt2d)
155>alias saveshape ? ({,,TKBRep}BRepTools_Write)
156>alias dumpshape ? ({,,TKBRep}BRepTools_Dump)
157>alias dumploc ? ({,,TKBRep}BRepTools_DumpLoc)
fc9b36d6 158>alias dumpmesh ? ({,,TKMesh}BRepMesh_Dump)
d4faf9e9 159>alias dumpgeom ? ({,,TKGeomBase}GeomTools_Dump)
160~~~~~
161
162Note that aliases are stored in the Visual Studio user's preferences and it is sufficient to define them once on a workstation. With these aliases, the above example can be reproduced easier (note the space symbol after alias name!):
163
164~~~~~
165>saveshape ("d:/edge1.brep",(void*)&anEdge1)
1660x04a2f234 "d:/edge1.brep"
167>dsetshape ("e1",(void*)&anEdge1)
1680x0369eba8 "e1"
169>deval ("donly e1; axo; fit")
1700x029a48f0 ""
171~~~~~
172
173Note that there is no guarantee that the call will succeed and will not affect the program execution, thus use this feature at your own risk. In particular, the commands interacting with window system (such as *axo*, *vinit*, etc.) are known to cause application crash when the program is built in 64-bit mode. To avoid this, it is recommended to prepare all necessary view windows in advance, and arrange these windows to avoid overlapping with the Visual Studio window, to ensure that they are visible during debug.
174
175@subsection occt_debug_vstudio_watch Customized display of variables content
176
177Visual Studio provides a way to customize display of variables of different types in debugger windows (Watch, Autos, Locals, etc.).
178
179In Visual Studio 2005-2010 the rules for this display are defined in file *autoexp.dat* located in subfolder *Common7\\Packages\\Debugger* of the Visual Studio installation folder (hint: the path to that folder is given in the corresponding environment variable, e.g. *VS100COMNTOOLS* for vc10). This file contains two sections: *AutoExpand* and *Visualizer*. The following rules can be added to these sections to provide more convenient display of some OCCT data types.
180
181### \[AutoExpand\] section
182
183~~~~~
184; Open CASCADE classes
185Standard_Transient=<,t> count=<count,d>
186Handle_Standard_Transient=<entity,x> count=<entity->count,d> <,t>
187TCollection_AsciiString=<mylength,d> <mystring,s>
188TCollection_HAsciiString=<myString.mylength,d> <myString.mystring,s>
189TCollection_ExtendedString=<mylength,d> <mystring,su>
190TCollection_HExtendedString=<myString.mylength,d> <myString.mystring,su>
191TCollection_BaseSequence=size=<Size,d> curr=<CurrentIndex,d>
192TCollection_BasicMap=size=<mySize,d>
193NCollection_BaseSequence=size=<mySize,d> curr=<myCurrentIndex,d>
194NCollection_BaseList=length=<myLength,d>
195NCollection_BaseMap=size=<mySize,d> buckets=<myNbBuckets>
196NCollection_BaseVector=length=<myLength,d>
197TDF_Label=<myLabelNode,x> tag=<myLabelNode->myTag>
198TDF_LabelNode=tag=<myTag,d>
199TDocStd_Document=format=<myStorageFormat.mystring,su> count=<count,d> <,t>
200TopoDS_Shape=<myTShape.entity,x> <myOrient>
201gp_XYZ=<x,g>, <y,g>, <z,g>
202gp_Pnt=<coord.x,g>, <coord.y,g>, <coord.z,g>
203gp_Vec=<coord.x,g>, <coord.y,g>, <coord.z,g>
204gp_Dir=<coord.x,g>, <coord.y,g>, <coord.z,g>
205gp_XY=<x,g>, <y,g>
206gp_Pnt2d=<coord.x,g>, <coord.y,g>
207gp_Dir2d=<coord.x,g>, <coord.y,g>
208gp_Vec2d=<coord.x,g>, <coord.y,g>
209gp_Mat2d={<matrix[0][0],g>,<matrix[0][1],g>}, {<matrix[1][0],g>,<matrix[1][1],g>}
210gp_Ax1=loc={<loc.coord.x,g>, <loc.coord.y,g>, <loc.coord.z,g>} vdir={<vdir.coord.x,g>, <vdir.coord.y,g>, <vdir.coord.z,g>}
211~~~~~
212
213### \[Visualizer\] section
214
215~~~~~
216; Open CASCADE classes
217
218NCollection_Handle<*> {
219 preview ( *((($T0::Ptr*)$e.entity)->myPtr) )
220 children ( (($T0::Ptr*)$e.entity)->myPtr )
221}
222
223NCollection_List<*> {
224 preview ( #( "NCollection_List [", $e.myLength, "]" ) )
225 children ( #list( head: $c.myFirst, next: myNext ) : #(*($T1*)(&$e+1)) )
226}
227
228NCollection_Array1<*> {
229 preview ( #( "NCollection_Array1 [", $e.myLowerBound, "..", $e.myUpperBound, "]" ) )
230 children ( #array( expr: $c.myData[$i], size: 1+$c.myUpperBound ) )
231}
232
233math_Vector {
234 preview ( #( "math_Vector [", $e.LowerIndex, "..", $e.UpperIndex, "]" ) )
235 children ( #array ( expr: ((double*)($c.Array.Addr))[$i], size: 1+$c.UpperIndex ) )
236}
237
238TColStd_Array1OfReal {
239 preview ( #( "Array1OfReal [", $e.myLowerBound, "..", $e.myUpperBound, "]" ) )
240 children ( #array ( expr: ((double*)($c.myStart))[$i], size: 1+$c.myUpperBound ) )
241}
242
243Handle_TColStd_HArray1OfReal {
244 preview ( #( "HArray1OfReal [",
245 ((TColStd_HArray1OfReal*)$e.entity)->myArray.myLowerBound, "..",
246 ((TColStd_HArray1OfReal*)$e.entity)->myArray.myUpperBound, "] ",
247 [$e.entity,x], " count=", $e.entity->count ) )
248 children ( #array ( expr: ((double*)(((TColStd_HArray1OfReal*)$e.entity)->myArray.myStart))[$i],
249 size: 1+((TColStd_HArray1OfReal*)$e.entity)->myArray.myUpperBound ) )
250}
251
252TColStd_Array1OfInteger {
253 preview ( #( "Array1OfInteger [", $e.myLowerBound, "..", $e.myUpperBound, "]" ) )
254 children ( #array ( expr: ((int*)($c.myStart))[$i], size: 1+$c.myUpperBound ) )
255}
256
257Handle_TColStd_HArray1OfInteger {
258 preview ( #( "HArray1OfInteger [",
259 ((TColStd_HArray1OfInteger*)$e.entity)->myArray.myLowerBound, "..",
260 ((TColStd_HArray1OfInteger*)$e.entity)->myArray.myUpperBound, "] ",
261 [$e.entity,x], " count=", $e.entity->count ) )
262 children ( #array ( expr: ((int*)(((TColStd_HArray1OfInteger*)$e.entity)->myArray.myStart))[$i],
263 size: 1+((TColStd_HArray1OfInteger*)$e.entity)->myArray.myUpperBound ) )
264}
265
266Handle_TCollection_HExtendedString {
267 preview ( #( "HExtendedString ", [$e.entity,x], " count=", $e.entity->count,
268 " ", ((TCollection_HExtendedString*)$e.entity)->myString ) )
269 children ( #([actual members]: [$e,!] ) )
270}
271
272Handle_TCollection_HAsciiString {
273 preview ( #( "HAsciiString ", [$e.entity,x], " count=", $e.entity->count,
274 " ", ((TCollection_HAsciiString*)$e.entity)->myString ) )
275 children ( #([actual members]: [$e,!],
276 #array( expr: ((TCollection_HAsciiString*)$e.entity)->myString.mystring[$i],
277 size: ((TCollection_HAsciiString*)$e.entity)->myString.mylength) ) )
278}
279~~~~~
280
618617fe 281In Visual Studio 2012 and later, visualizers can be put in a separate file in subdirectory *Visualizers*. See file *occt.natvis* for example.
282
283@section occt_debug_perf Performance measurement tools
284
285It is recommended to use specialized performance analysis tools to profile OCCT and application code.
8d44b0a0 286However, when such tools are not available or cannot be used for some reason, tools provided by OSD package can be used: low-level C functions and macros defined in *OSD_PerfMeter.h* and *OSD_PerfMeter* class.
287
288This tool maintains an array of 100 global performance counters that can be started and stopped independently. Adding a performance counter to a function of interest allows to get statistics on the number of calls and the total execution time of the function.
289* In C++ code, this can be achieved by creating local variable *OSD_PerfMeter* in each block of code to be measured.
290* In C or Fortran code, use functions *perf_start_meter* and *perf_stop_meter* to start and stop the counter.
291
292Note that this instrumentation is intended to be removed when the profiling is completed.
293
294Macros provided in *OSD_PerfMeter.h* can be used to keep instrumentation code permanently but enable it only when macro *PERF_ENABLE_METERS* is defined.
618617fe 295Each counter has its name shown when the collected statistics are printed.
296
8d44b0a0 297In DRAW, use command *dperf* to print all performance statistics.
618617fe 298
299Note that performance counters are not thread-safe.