Using C++View with ReplayEngine
In general, C++View can be used with ReplayEngine just as with normal TotalView debugging. However, there are some differences you should be aware of. In both record mode and replay mode, TotalView switches your process into ReplayEngine’s volatile mode before calling your TV_ttf_display_type function. When the call finishes, TotalView switches the process out of volatile mode. On entering volatile mode, ReplayEngine saves the state of the process, and on exiting volatile mode, ReplayEngine restores the saved status.
In most cases, executing TV_ttf_display_type in volatile mode behaves as you would expect. However, because ReplayEngine restores the earlier process state when it leaves volatile mode, any changes to process memory, such as writing to a variable, made while in volatile mode are lost.
This fact has implications for your program if your
TV_ttf_display_type function modifies global or static data upon which either the function or the program relies. If
TV_ttf_display_type does not change any global state, you will see no change in behavior when you engage ReplayEngine. However, if you generate synthetic values, such as the average, maximum or minimum values in an array, you cannot compute these in your
TV_ttf_display_type function as the results will be lost when the function call terminates. Instead, consider generating them as a by-product of the program’s normal execution as described in the section on
Memory Management.
For more information on ReplayEngine, see
Getting Started with ReplayEngine.
The following code demonstrates how engaging ReplayEngine might affect calls to TV_ttf_display_type. This example is shipped with the ReplayEngine example files as cppview_example_5.cc.
/* Example program demonstrating TotalView's C++View with ReplayEngine. */
/* Run with (in both record and replay modes) and without ReplayEngine. */
/* Note how c in main is displayed in the various cases. */
#include <stdio.h>
#include "tv_data_display.h"
static int counter;
class C {
public:
int value;
C () : value ( 0 ) {};
}; /* C */
int
TV_ttf_display_type(const C *c)
{
int ret_val = TV_ttf_format_ok;
int err;
// if Replay is engaged, this write to the global is lost because
// the ttf function is evaluated in volatile mode
counter++;
// error checking omitted for brevity
(void) TV_ttf_add_row ( "value", "int", &(c->value) );
// show how many times we've been called. Will always be zero
// with Replay engaged because the update is lost when the
// call to TV_ttf_display_type returns.
(void) TV_ttf_add_row ( "number_of_times_called", "int", &counter );
return ret_val ;
} /* TV_ttf_display_type */
int main(int argc, char *argv[])
{
C c;
c.value = 1;
c.value++; // should be 1 **before** this line is executed
c.value++; // should be 2 **before** this line is executed
/* c.value should be 3 */
return 0;
} /* main */
Compile and link the program with
tv_data_display.c (see
Compiling and linking tv_data_display.c). Follow this procedure:
1 Start the program under TotalView and enter the function main.
2 Dive on the local variable c, and note how the synthetic member number_of_times_called changes as you step through the program.
3 Restart, but this time with ReplayEngine engaged.
4 Notice the changes to the value member as you move forwards and backwards, and that the synthetic member number_of_times_called remains 0 because the increment in TV_ttf_display_type is lost when the function returns.