Is there a way to print an Armadillo matrix in gdb?

允我心安 提交于 2019-12-19 06:39:11

问题


I'm using gdb to debug my c++ program. I'm using the armadillo numerical library to define my matrices. I have an armadillo matrix defined like so:

mat A = randu<mat>(5,5);

Is it possible to print the whole matrix while using the gdb debugger?


回答1:


The question may be old, but stumbling over it made me find a solution for my own work.

Due to the template-based nature of the Armadillo library you need to provide some helpers of your own:

#include <iostream>
#include <armadillo>

template<class Matrix>
void print_matrix(Matrix matrix) {
    matrix.print(std::cout);
}

//provide explicit instantiations of the template function for 
//every matrix type you use somewhere in your program.
template void print_matrix<arma::mat>(arma::mat matrix);
template void print_matrix<arma::cx_mat>(arma::cx_mat matrix);

int main() {
    arma::mat matrix = arma::randu(10,10);

    return 0;
}

Now you can easily call print_matrix from within gdb:

(gdb) call print_matrix<arma::Mat<double> >(matrix) 
   0.8402   0.4774   0.0163   0.5129   0.5267   0.5260   0.2383   0.5316   0.6879   0.9565
   0.3944   0.6289   0.2429   0.8391   0.7699   0.0861   0.9706   0.0393   0.1660   0.5886
   0.7831   0.3648   0.1372   0.6126   0.4002   0.1922   0.9022   0.4376   0.4401   0.6573
   0.7984   0.5134   0.8042   0.2960   0.8915   0.6632   0.8509   0.9318   0.8801   0.8587
   0.9116   0.9522   0.1567   0.6376   0.2833   0.8902   0.2667   0.9308   0.8292   0.4396
   0.1976   0.9162   0.4009   0.5243   0.3525   0.3489   0.5398   0.7210   0.3303   0.9240
   0.3352   0.6357   0.1298   0.4936   0.8077   0.0642   0.3752   0.2843   0.2290   0.3984
   0.7682   0.7173   0.1088   0.9728   0.9190   0.0200   0.7602   0.7385   0.8934   0.8148
   0.2778   0.1416   0.9989   0.2925   0.0698   0.4577   0.5125   0.6400   0.3504   0.6842
   0.5540   0.6070   0.2183   0.7714   0.9493   0.0631   0.6677   0.3540   0.6867   0.9110

Thanks to tab completion you only need to actually type a few characters of print_matrix<arma::Mat<double> >.




回答2:


You can call C functions in gdb, so you just need a function that prints your objects. E.g:

(gdb) call printf("%.2f", 3.1428)
$7 = 4
(gdb) call fflush(stdout)
3.14$8 = 0



回答3:


For those using QtCreator, you can inspect the values from your IDE by extending GDB with Python Debugging Helpers (maybe other IDEs support this feature too).

Place the following script in, for example, ~/debugHelpers.py

#!/usr/bin/python

import gdb      # gdb.Value()
import dumper   # dumper.Children()

def qdump__arma__Mat(d, value):
    array = value["mem"]
    cols = value["n_cols"]
    rows = value["n_rows"]
    maxDisplayItems = 50
    innerType = d.templateArgument(value.type, 0)
    p = gdb.Value(array.cast(innerType.pointer()))
    d.putItemCount(cols)
    d.putNumChild(cols)
    if d.isExpanded():
        numDisplayItems = min(maxDisplayItems, cols)
        with dumper.Children(d, numChild=cols,
               maxNumChild=numDisplayItems,
               childType="<column>",
               addrBase=p,
               addrStep=p.dereference().__sizeof__):
            for i in range(0, int(numDisplayItems)):
                with dumper.Children(d):
                    d.putItemCount(rows)
                    d.putNumChild(rows)
                    if d.isExpanded():
                        numDisplayItems = min(maxDisplayItems, rows)
                        with dumper.Children(d, numChild=rows,
                               maxNumChild=numDisplayItems,
                               childType=innerType,
                               addrBase=p,
                               addrStep=p.dereference().__sizeof__):
                            for j in range(0, int(numDisplayItems)):
                                d.putSubItem(j, p.dereference())
                                p += 1

And call it adding this line to your ~/.gdbinit:

python exec(open('/<full_path>/debugHelpers.py').read())

or add it from your IDE; in QtCreator use Tools > Options > Debugger > GDB (tab) > Extra Debugging Helpers (near the bottom).

This particular script will return the matrix arranged by columns (natural memory arrangement in my architecture):

Sources: Writing Debug Visualizers for GDB / QtCreator 2.8




回答4:


The best option is using gdb's python API to create pretty printers for the armadillo classes. It works better than calling a C/C++ function, since it is always accessible (even when debugging from a core file where there is no program running). Furthermore, there is no risk of the linker discarding the function when it is not used in your program (thus making it unavailable when you are debugging in gdb).

The pretty printer code is loaded (sourced) from the .gdbinit file in your home folder. It will work in gdb running in a terminal as well as from an IDE (assuming the IDE does not avoid loading the .gdbinit file).

As an example, suppose you have the following two matrices

arma::mat m1{{1.1, 2.2,  3},
             {  4,   5,  6}, 
             {  7,   8,  9},
             { 10,  11, 12},
             { 13,  14, 15},
             { 16,  17, 18}};

arma::cx_mat m2{{1.1 - 1.1j, 2.2 - 7.7j, 3},
                {         4,          5, 6},
                {         7,          8, 9},
                {         10,        11, 12},
                {         13,        14, 15},
                {         16,        17, 18}};

A pretty printer might shown them as

Notice how the complex matrix m2 has its elements displayed both in rectangular form as well as in polar form (displaying the polar form can be disabled). This also works better with the rest of gdb. For instance, gdb allows you to the maximum number of elements to show in an array. The pretty printer will respect that if it is implemented to display the elements as standard arrays in gdb.


This is how the m1 and m2 matrices are displayed in CLion.


This pretty printer can be obtained from here. There are a few other things such as some xmethods (python re-implementation of some C++ methods) and conversion to numpy arrays.

Disclaimer: I'm the author of these pretty printers.




回答5:


The simplest way is to print directly in gdb, unfortunately no fancy format

> print *A.mem@5@5
$1 = {{0.84018771715470952, 0.39438292681909304,0.78309922375860586,0.79844003347607329, 0.91164735793678431},
{0.19755136929338396, 0.33522275571488902, 0.768229594811904, 0.27777471080318777, 0.55396995579543051}, 
{0.47739705186216025, 0.62887092476192441, 0.36478447279184334, 0.51340091019561551, 0.95222972517471283}, 
{0.91619506800370065, 0.63571172795990094, 0.71729692943268308, 0.14160255535580338, 0.60696887625705864}, 
{0.016300571624329581, 0.24288677062973696, 0.13723157678601872, 0.80417675422699042, 0.15667908925408455}}


来源:https://stackoverflow.com/questions/9499445/is-there-a-way-to-print-an-armadillo-matrix-in-gdb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!