Debugging

Tracing of public methods

When using multi_type_vector to handle a series of data reads and writes in an non-trivial code base, sometimes you may find yourself needing to track which methods are getting called when following a certain code path during a debugging session. In such a situation, you can enable an optional trace method which gets called whenever a public method of multi_type_vector is called.

First, you need to define a preprocessor macro named MDDS_MULTI_TYPE_VECTOR_TRACE before including the header for multi_type_vector:

#define MDDS_MULTI_TYPE_VECTOR_TRACE 1
#include <mdds/multi_type_vector/soa/main.hpp>

#include <iostream>

to enable additional call-tracinng code. In this example the value of the macro is set to 1, but it doesn’t matter what the value of the macro is as long as it is defined. You can also define one as a compiler option as well.

Once defined, the next step is to add a trace method as a static function to the trait type you pass as a template argument of multi_type_vector:

namespace mtv = mdds::mtv;

struct mtv_traits : public mtv::standard_element_blocks_traits
{
    static void trace(const mtv::trace_method_properties_t& props)
    {
        std::cout << "function:" << std::endl
                  << "  name: " << props.function_name << std::endl
                  << "  args: " << props.function_args << std::endl;
    }
};

using mtv_type = mtv::soa::multi_type_vector<mtv_traits>;

Here, we are simply inheriting our trait type from the default_traits type and simply adding a static trace function to it, and passing this trait type to the mtv_type definition below. This trace function must take one argument of type mdds::mtv::trace_method_properties_t which includes various properties of the traced call. In this example, we are simply printing the properties named function_name and function_args each time a traced method is called. Both of these properties are printable string types.

Note that this trace function is entirely optional; the code will compile fine even when it’s not defined. Also, it must be declared as static for it to be called.

Let’s instantiate an object of mtv_type, call some of its methods and see what happens. When executing the following code:

mtv_type db(10);
db.set<int32_t>(0, 12);
db.set<int8_t>(2, 34);
db.set<int16_t>(4, 56);

You will see the following output:

function:
  name: multi_type_vector
  args: init_size=10
function:
  name: set
  args: pos=0; value=? (type=5)
function:
  name: set
  args: pos=2; value=? (type=1)
function:
  name: set
  args: pos=4; value=? (type=3)
function:
  name: ~multi_type_vector
  args:

The function_name property is hopefully self-explanatory. The function_args property is a single string value containing the information about the function’s arguments and optionally their values if their values are known to be printable. If the value of an argument cannot be printed, ? is placed instead. For some argument types, an additional information is displayed e.g. (type=5) in the above output which indicates that the type of the value being passed to the function is element_type_int32.

If you want to limit your tracing to a specific function type or types, you can make use of the type property which specifies the type of the traced method. Likewise, if you want to only trace methods of a certain instance, use instance to filter the incoming trace calls based on the memory addresses of the instances whose methods are being traced.

Note that this feature is available for version 2.0.2 and newer, and currently only available for the SoA variant of multi_type_vector.

Note

This feature is only available for version 2.0.2 and newer, and only for the SoA variant.