0

I have been using Blitz array package last few days. During debug I require to print the array contents, and blitz supports something like below

std::cout<<blitz_array_name<<std::endl

I would like to print the array contents via GDB during debug. So i wrote overloaded functions for different type of arrays which I like to prin, like below

void printBlitz(blitz::Array<bool, 1> &in)
{
std::cout<<in<<std::endl;
}

void printBlitz(blitz::Array<int, 1> &in)
{
std::cout<<in<<std::endl;
}

... and so on

on the gdb debugger, I can simply call this function as below

(gdb) call printBlitz(blitz_array_name)
  1. The issue now is I am using many many types of multi-dimensional arrays, I have to make overloads for every array
  2. Am not able to call template functions via GDB's call feature - this would also help
  3. I tried to do something like below

(gdb) define printmyvar call (void)operator<<(std::cout, $arg0) print "\n" end

when i try to print the array as below

(gdb) printmyvar blitz_array_name

I get this error "Cannot resolve function operator<< to any overloaded instance"

d) I can define a macro as below

   PRINTBLITZ(myvar) std::cout<<myvar<<std::endl

but via GDB i cannot pass a macro and execute it.

How can we simply execute something like below from GDB

std::cout<<myvar<<std::endl

Please suggest any solution for this issue. Any suggestion is highly appreciated, and accelerate my debug.

Thank you so much in advance !!

CutePoison
  • 131
  • 1
  • 6

1 Answers1

1
  1. Am not able to call template functions via GDB's call feature - this would also help

Actually, after trying a few alternatives it seems that you can, but it is hard to dot it properly.

Consider the following code

#include <iostream>

double tripleInput(double x) { return 3 * x; }

template <typename T>
inline T doubleInput(T x) {
    return 2 * x;
}


int main(int argc, char *argv[])
{
    std::cout << doubleInput(13) << std::endl;
    std::cout << doubleInput(1.72) << std::endl;

    std::cout << tripleInput(1.72) << std::endl;
    return 0;
}

After compiling with debug symbols and starting gdb with the executable we can do

call tripleInput(1.5)

and gdb will return 4.5. So far so good. Note however, that if you write call tri and press TAB gdb will complete the name as tripleInput(double). After that you add (1.5) and you can run as

tripleInput(double)(1.5)

which will work as before.

Now let's try with the templated doubleInput function. That is the name of the template, but only once you use the template with some type is that the compiler will generate a function from the template. The actual names are doubleInput<int>, doubleInput<double>, etc. Only versions you have actually used will be in the binary and can be seen by gdb.

Now let's try

call doubleInput<double>(1.7)

and gdb returns 3.3999999999999999. Great! Notice that

call doubleInput<double>(double)(1.7)

works as well. Just beware that

call doubleInput<int>(1.7)

returns 2, instead of 3.3999999999999999, but that makes sense.

So, the answer is that you can call instances of the template, as long as you pass the full name (use TAB to complete the name).

Just a final note, if I change the tripleInput and doubleInput to receive the argument by reference, instead of by value, then it won't work and I get the error "Attempt to take address of value not located in memory".


  1. The issue now is I am using many many types of multi-dimensional arrays, I have to make overloads for every array

With the previous answer, it means that you could write a single template instead of multiple implementations. Just be sure to call it once. Even if you do implement several functions, you still need to call them such that the linker does not remove it from the binary.


But in order to help debugging the best solution, by far, is using gdb's Python API to write custom pretty printers for bliz::Array types. If you had pretty printers for blitz types and all you needed to see a blitz::Array was p variable_name. This would always work even if you are debugging from a core file (without an inferior running you can't call a function).

Unfortunately, I could not find any existing implementation of pretty printers for blitz, which means that you would have to write it yourself.

I don't have experience with blitz, but I often use armadillo, which is a C++ library for linear algebra & scientific computing, and I have written pretty printers for armadillo types. See this answer and this repository if you are curious.

Writing pretty printers requires you to understand a little about the way that the type you are writing pretty printers for stores its data. You will need to read gdb's documentation about it, but the best way is to look other implementations of pretty printers. At least that's how I've done it.

darcamo
  • 3,294
  • 1
  • 16
  • 27