![]() |
![]() |
![]() |
![]() |
13 Debugging Objects
This chapter describes techniques for debugging AVS/Express objects. It includes the following sections:
This section describes how to debug a network that does not work, including whether and when methods are firing. After providing general debugging guidelines, it discusses three ways to obtain information about what is happening in a network:
- Access information about objects in the network.
- Trace method execution.
- Trace operations on specific objects.
Note that this chapter frequently provides V-code examples and refers to C API routines.
For detailed information on V code, see Chapter 7, V and the V Command Processor.
For information on equivalent C++ API and FORTRAN API routines, see Chapter 9, Object Manager APIs.
For reference descriptions of specific Object Manager API routines, see the AVS/Express on-line help.
Many of the general guidelines for debugging applications also apply to debugging AVS/Express networks and methods. They include the following:
- Try to isolate where in the network the problem is located. This is easier if you simplify the network as much as possible.
- Use simple test data. For example, if the network gets data from a database, create a simple test file and read it with Read_Column_File. This will enable you to see whether the problem is with retrieving data from the database or elsewhere in the network.
- Test modularly after completing each step in the network; that is, verify that each component works before fully connecting the network. For example, if you develop a reader, do not connect its output to a Field Mapper, five visualization modules, and into a viewer before you test it. Instead, read the data, verify that the output looks as expected, and then connect the output to the rest of the network.
- Initially, link new or revised modules into an external process (such as user) during development. A module that runs in an external process does not bring down all of AVS/Express if it causes runtime errors. Once the module is executing correctly, you can move it from the external process to the express process.
Accessing object information involves traversing objects in the network, examining their values and connections. You can access most AVS/Express data through the Network Editor and/or the V Command Processor (VCP).
- In the Network Editor, you simply traverse down to an object in the network that contains real data values. The object's value is displayed on its icon or within the typein that it displays when you open it.
- In the VCP, you use V commands to access an object's information explicitly. This process is more complex, but using V commands provides more information than you can get in the Network Editor.
- The following V commands are useful for debugging networks.
For more information on particular V commands, see Chapter 7, V and the V Command Processor.
Tracing method execution helps you to determine what methods the Object Manager attempts to execute and in what order. You typically need to trace method execution because one of the following has occurred:
- The Object Manager did not execute a method when expected, either because the method required a parameter value that was absent or not valid or because the method was never called.
- The Object Manager called a method but the expected output was not produced.
In order to trace method execution, you must set verbose mode:
- In the Network Editor, turn on the Options->Verbose Functions flag.
- In the VCP, use the following V command:
When it is in verbose mode, AVS/Express displays in the VCP messages returned by the Object Manager when it attempts to execute functions. These messages, called verbose messages, appear in the VCP window. They provide information such as which requests the Object Manager puts into its request queue, which methods it executes, and why it executes them.
- In the Network Editor, turn off the Options->Verbose Functions flag.
- In the VCP, use the following V command:
The following example illustrates the verbose messages returned when the Object Manager tries to execute a method with a required parameter whose value is absent or not valid. Suppose that you set verbose mode and then intend to instantiate the module add_num. This module's V definition is as follows:
module add_num {
float+IPort2+read+req src_1;
float+IPort2+read+req src_2;
float+OPort2+write+nonotify res;
omethod+notify+req+notify_inst update = "USERadd_num";
}
When you instantiate add_num, the Object Manager returns the following verbose messages:
OM:executing:
func : SingleWindowApp.add_num.update
arg : SingleWindowApp.add_num
events : object instanced
cause : SingleWindowApp.add_num
--- Error detected in: module: OMprim_valid_obj ---
object: Root.Applications.SingleWindowApp.add_num.src_1 does
not have a value
--------------------------------------------------
OM:is not valid:
func : SingleWindowApp.add_num.update
arg : SingleWindowApp.add_num
events : object instanced
The Object Manager reports that the update method of the add_num module is not valid. Here is the reason: the notify_inst attribute is set on the update method for this module, so the Object Manager attempted to execute the method when you instanced it. However, the required input port values were both absent and therefore invalid; therefore, the execution attempt failed.
If you now assign a value to the module's src_1 input port but not to its src_2 input port, the Object Manager again tries to execute the method and again fails. AVS/Express returns the following verbose methods:
OM:executing:
func : SingleWindowApp.add_num.update
arg : SingleWindowApp.add_num
events : value changed
cause : SingleWindowApp.add_num.src_1
--- Error detected in: module: OMprim_valid_obj ---
object: Root.Applications.SingleWindowApp.add_num.src_2 does
not have a value
--------------------------------------------------
OM:is not valid:
func : SingleWindowApp.add_num.update
arg : SingleWindowApp.add_num
events : value changed
If you now assign a value to the module's src_2 input port, the Object Manager successfully executes the method. AVS/Express returns the following verbose messages:
OM:executing:
func : SingleWindowApp.add_num.update
arg : SingleWindowApp.add_num
events : value changed
cause : SingleWindowApp.add_num.src_2
done : SingleWindowApp.add_num.update
The indentation level of a verbose message indicates the level of nesting of OMpush_ctx/OMpop_ctx routines at the time that the module runs. If the first line of the message is indented by three spaces, the method's execution is being controlled by the explicit use of OMpush_ctx/OMpop_ctx by another running method.
You may observe from returned messages that the Object Manager does not call a method when you expect it to. There are a number of reasons why this might happen:
The notify property should be set on a parameter but is not. To verify whether this property is set:
1. In the Network Editor, go to the library containing the module, select the module, and select Object->Object Editor.
2. In the Object Editor, select the parameter and then select Parameters from the Editor option menu.
A required parameter has not been set. Using the Object Editor in a similar manner, check which parameters are required and ensure that they all have valid values.
No values have changed for those parameters whose notify property has been set.
If the Object Manager calls your method and, while it apparently executes correctly, you do not see any output, do the following:
- Ensure that you have set the output parameter(s). For example, if your method is implemented in C code, you call the OMset_call function.
- Ensure that you have called ARRfree for all relevant arrays.
If the method is called and its output is set, but you see unexpected output values, you must debug the code that implements the method.
A method returns either one of two values to indicate its execution status:
If a method fails, any methods with a required dependency on the outputs of the method will not be triggered. Consider this simple example:
If the method for subtract_num fails, the method for add_num is not executed. The verbose messages returned by the Object Manager confirm this:
OM:executing:
func : SingleWindowApp.subtract_num.update
arg : SingleWindowApp.subtract_num
events : value changed
cause : SingleWindowApp.subtract_num.src_1
--- Error detected in: module: OMprim_valid_obj ---
object: Root.Applications.SingleWindowApp.subtract_num.src_2 does
not have a value
--------------------------------------------------
OM:is not valid:
func : SingleWindowApp.subtract_num.update
arg : SingleWindowApp.subtract_num
events : value changed
OM:tossing event because required dependency is invalid:
func : SingleWindowApp.add_num.update
arg : SingleWindowApp.add_num
events : value changed
cause : SingleWindowApp.subtract_num.update
When debugging, it is often useful to trace the operations that occur on specific objects. For example, if the value of an object is being changed and you do not know which method is responsible, you can trace the set_val operations that occur on that object.
AVS/Express can trace the following operations:
By default, AVS/Express traces only set_val operations. You can change the operations that it traces by using the following commands in the VCP:
These commands set and unset the trace operation for a specified list of operations.
To trace events on a specific object, set the trace attribute on it.
If you are using a source debugger on the process that is performing the operation, you can set a break point in the function OM_stop_here. This function is called each time that a trace message is printed.
A number of additional Object Manager API routines and V commands may be useful in debugging networks. The C API versions are as follows:
For information on equivalent C++ API and FORTRAN API routines, see Chapter 9, Object Manager APIs.
For more information on these V commands, see Testing and Debugging Applications on page 7-41.
You debug a module by using a standard source debugger on the process in which the module runs. You can debug a module running in either the AVS/Express main process or an external process started by the main process.
Before you can use the debugger on the process, you must compile your application so as to produce debuggable symbols. To do this, you specify the appropriate compilation flag as the value of the G make variable, then invoke the express makefile using this value. For most UNIX compilers, the required compilation flag is -g; for Windows compilers, it is usually /Zi or -Zi. (See your debugger documentation for details.)
There are two ways to set the G make variable.
- Set it directly on the command line when you invoke the express makefile. On UNIX-based machines, you typically use this command:
- On Windows-based machines, you typically use one of these commands:
- Set it in machinc.mk, the machine-specific portion of the AVS/Express makefile. The default machinc.mk file is located in the following directory:
- Copy the machinc.mk file from this directory into the following directory in your own project:
- In the machinc.mk file, the G make variable is set by default to -O. On UNIX machines, you typically change it to the following:
- On Windows machines, you typically change it to one of the following:
To debug a module that runs in the AVS/Express main process (typically the express process), simply start your debugger in the normal way on the main process. For example, on an UNIX-based system, you might use a command such as the following:
For Windows-based machines, you might start Visual C++ and use it to debug the main process.
Once the debugger is running, set break points in the functions defined for your module. When you interrupt the process in this way, AVS/Express catches the interrupt signal and exits cleanly.
- Note: On some UNIX platforms, the express process exits improperly when you interrupt and continue in the debugger. A workaround for this problem is to prevent AVS/Express from catching the interrupt signal. To do this, set the environment variable OM_NO_CRASH_HANDLER before you start the debugger on the express process.
An external process is a child process started by the main (typically express) process; for example, a user process. The main process creates a user process when you instantiate an object in the Network Editor's workspace. That object runs in the user process, as do any other objects subsequently instantiated in the same workspace. When you delete the last object in the user process from the workspace, the main process deletes the user process.
For example, suppose that you start the express process and instantiate the add_num module (from the AVS/Express library Library_Workspaces.User_Functions). The express process creates a user process, in which add_num runs. You then instantiate subtract_num (located in the same library), which runs in the same user process as add_num. Now, you delete both subtract_num and add_num. Since the user process now contains no modules, it is no longer needed and is deleted. If you instantiate add_num again, the express process creates a new user process for it.
The following figures provide another example. Suppose that you start an AVS/Express application that contains the following network:
All of the modules in this network run in the express process. Now, suppose that you instantiate the add_num module in the same workspace.
The express process creates a user process in which add_num runs. The other modules continue to run in the express process.
If you want to debug a module that runs in an external process, you must attach to that process to use a debugger on it. Note that if you set a break point in the method of a module that runs in an external process, execution will not reach the break point, and the debugger will not break, until the method fires. This, in turn, does not happen until you assign values to all of the module's required parameters. Therefore, even though you attach to a user process, you must ensure that the method fires in order to reach the break point. In the previous example, you must assign values to both the both the src_1 and src_2 parameters before the method fires.
How you debug an external process varies depending on whether you are running AVS/Express on a UNIX machine or a Windows machine.
On UNIX machines, you debug an AVS/Express external process by using an AVS-supplied script that starts a debugger and facilitates attaching it to the external process. This script, called xp_dbg, resides in the directory express_install_dir/bin. (Because scripts are not machine specific, this file does not need to reside in the machine_type subdirectory.) By default, the xp_dbg script starts the default debugger for your system. You can change this either by editing the script directly or specifying the appropriate command-line option, as noted in the following procedure.
To debug an external process using the xp_dbg script:
1. Ensure that the module was compiled with debuggable symbols (see Debugging Modules on page 13-10).
2. (Optional) Using the editor of your choice, edit the xp_dbg script to specify a debugger other than the default debugger for your system.
3. Create a new terminal window on your machine. The rest of this procedure refers to this window as Terminal 2.
- Note: Use Terminal 2 only if a step explicitly instructs you to do so.
4. Delete any modules that are running in the external process to be debugged, so that the process is not active.
5. Determine the name of the external process to be debugged (these processes are stored in the directory express_install_dir/bin/machine_type).
6. In Terminal 2, change your current directory to your AVS/Express project directory and run the xp_dbg script. To start it using the debugger specified in the script, use this command:
- To start it but override the debugger specification in the script, use this command:
- The debugger opens and responds with its typical prompt.
8. In AVS/Express, instantiate the module that you want to debug. A message like the following appears in Terminal 2:
9. Within 15 seconds after this message appears, enter the following debugger command in Terminal 2:
- Note: If you do not type this command before the wait period times out, AVS/Express stops waiting and executes the process.
10. Build the network necessary to execute the module. When the module's method fires, the debugger stops at the break point.
On Windows machines, you use MSDEV, the Visual C++ debugger, to debug an AVS/Express external process. When you start MSDEV, you specify the process ID of the external process on the command line.
To determine the process ID of an external process:
c. In the Processes page, locate the external process to be debugged and find its process ID in the PID column.
3. (Windows NT machines prior to 4.0) Using the MSDEV pstat command, obtain process statistics about the external process to be debugged. For example:
- This command returns output such as the following:
0:00:00.420 0:00:00.550 2624 75 1032 8 47 2 248 user.exe
pid: f8 pri: 8 Hnd: 47 Pf: 753 Ws: 2624K user.exe
- The process number is the number immediately before the first occurrence of the process name; in this example, 248.
- Note: If you are debugging a user process, be sure to select the correct user process. Windows NT also uses a process called user.exe; this is not the correct user process.
To debug the external process:
1. Ensure that the module was compiled with debuggable symbols (see Debugging Modules on page 13-10).
- You can run this command from either a command shell or the Desktop (Start->Run on Windows NT 4.0 or Program Manager->File->Run on Windows NT 3.51). If you have already set environment variables, or you need to set them in a command shell, then run MSDEV from the command shell rather than from the Desktop.
AVS/Express provides Object Manager API routines that you can call from your debugger to obtain diagnostic information about the state of your objects while your module is executing. This section describes the C API versions; for information on the equivalent C++ API and FORTRAN API routines, see Chapter 9, Object Manager APIs.
While in a debugging session, you can call the OMedit_root_obj routine to bring up the VCP temporarily. When you call this function, the VCP begins by editing the Root object. To exit the VCP and return your debugging session, issue the EOF character (usually Ctrl-d).
If you have a variable that contains OMobj_id, you can bring up the VCP directly on that object by calling the OMedit_obj routine. This feature works only if your debugger allows you to pass arguments to the functions. This function takes a single OMobj_id as an argument.
To determine the pathname of a variable that contains OMobj_id, call the OMprint_path routine. This routine takes a single OMobj_id argument and prints the pathname of the object passed to the console window.
Some debuggers do not allow you to pass structures by value as arguments to routines that you call from them. If this is true for your debugger, you cannot call the OMedit_obj and OMprint_path routines directly because each takes an OMobj_id as its first and only argument. Instead, you must call the OMedit_obj_ptr and OMprint_path_ptr routines. These routines each take two arguments that correspond to the elem_id and proc_id fields of OMobj_id. For example:
There are two likely reasons why a method is not called when you change a parameter's value:
- The parameter is not properly specified with the notify flag.
- One of the method's parameter is marked as required and does not have a valid value.
The first step in determining the problem is to set verbose mode as described in Tracing Method Execution on page 13-4. In verbose mode, the Object Manager returns a messages that appear in the VCP whenever it attempts to execute a method.
If you change the parameter that should cause your method to execute but you do not see any messages printed, you may not have set notifications properly on the parameter. In the VCP, go to the parameter and use the $notify command on the object.
If AVS/Express tries to run your method but finds an invalid required parameter, use the verbose messages that appear to identify the parameter.
See Required Parameter Value Is Absent or Not Valid on page 13-4.
You can also track down an invalid parameter in the VCP as follows:
3. If the method is not valid, use $valid on each required parameter one at a time until you find the one that is not valid.
For information on $notify and $valid, see Chapter 7, V and the V Command Processor.
If you find that two methods are executing in the incorrect order, check the order in which they are defined to run. The method that runs last should be dependent on the method that runs first, not the reverse.
See Controlling Method Execution Order on page 8-13.
To examine the dependencies of a particular method in the VCP, use the $deps command.
For information on $deps, see Chapter 7, V and the V Command Processor.
![]() |
![]() |
![]() |
![]() |